From c3b2dc878dcd9ed910a578b1b28912a90f07959f Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Mon, 18 Sep 2017 20:40:01 +0000 Subject: [PATCH] Ajax to remove OIDC consent (#826) --- fastcgi-server/man/llng-fastcgi-server.1p | 2 +- .../lib/Lemonldap/NG/Portal/Main/Display.pm | 14 +++++-- .../Lemonldap/NG/Portal/Plugins/RESTServer.pm | 40 +++++++++++++++--- lemonldap-ng-portal/site/coffee/portal.coffee | 26 ++++++++++-- .../site/htdocs/static/common/js/portal.js | 41 +++++++++++++++---- .../htdocs/static/common/js/portal.min.js | 2 +- 6 files changed, 102 insertions(+), 23 deletions(-) diff --git a/fastcgi-server/man/llng-fastcgi-server.1p b/fastcgi-server/man/llng-fastcgi-server.1p index 9ee5b82f9..ac7317adb 100644 --- a/fastcgi-server/man/llng-fastcgi-server.1p +++ b/fastcgi-server/man/llng-fastcgi-server.1p @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "llng-fastcgi-server 1" -.TH llng-fastcgi-server 1 "2017-09-05" "perl v5.26.0" "User Contributed Perl Documentation" +.TH llng-fastcgi-server 1 "2017-09-18" "perl v5.26.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm index 1731aed6b..7b05c98ff 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -6,6 +6,7 @@ our $VERSION = '2.0.0'; package Lemonldap::NG::Portal::Main; use strict; +use Mouse; has skinRules => ( is => 'rw' ); @@ -468,9 +469,16 @@ sub mkOidcConsent { . ''; # TODO: add JS to remove consent - $tmp .= "$_" - foreach ( split /,/, $session->{_oidcConnectedRP} ); - $tmp .= ''; + if ( $session->{_oidcConnectedRP} ) { + $tmp .= +qq'$_ remove' + foreach ( split /,/, $session->{_oidcConnectedRP} ); + $tmp .= qq''; + } return $tmp; } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm index 06b6f6515..52600519b 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm @@ -88,6 +88,17 @@ has exportedAttr => ( } ); +has ott => ( + is => 'rw', + lazy => 1, + default => sub { + my $ott = + $_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken'); + $ott->timeout( $_[0]->conf->{formTimeout} ); + return $ott; + } +); + # INITIALIZATION sub init { @@ -294,6 +305,11 @@ sub mysession { { result => $req->userData->{ $self->conf->{whatToTrace} } } ); } + if ( defined $req->param('gettoken') ) { + return $self->p->sendJSONresponse( $req, + { token => $self->ott->createToken() } ); + } + # Verify authorizationfor arg elsif ( my $url = $req->param('authorizationfor') ) { @@ -338,14 +354,26 @@ sub updateMySession { my ( $self, $req ) = @_; my $res = 0; my $mKeys = []; - if ( $req->param('sessionType') eq 'persistent' ) { - foreach my $key (qw(_appsListOrder)) { - if ( my $v = $req->param($key) ) { - $res++; - push @$mKeys, $key; - $self->p->updatePersistentSession( $req, { $key => $v } ); + if ( my $token = $req->param('token') ) { + if ( $self->ott->getToken($token) ) { + if ( $req->param('sessionType') eq 'persistent' ) { + foreach my $key (qw(_appsListOrder _oidcConnectedRP)) { + my $v = $req->param($key); + if ( defined $v ) { + $res++; + push @$mKeys, $key; + $self->p->updatePersistentSession( $req, + { $key => $v } ); + } + } } } + else { + $self->logger->error('Update session request with invalid token'); + } + } + else { + $self->logger->error('Update session request without token'); } unless ($res) { return $self->p->sendError( $req, 'Modification refused', 403 ); diff --git a/lemonldap-ng-portal/site/coffee/portal.coffee b/lemonldap-ng-portal/site/coffee/portal.coffee index fe1827c83..6395b5f31 100644 --- a/lemonldap-ng-portal/site/coffee/portal.coffee +++ b/lemonldap-ng-portal/site/coffee/portal.coffee @@ -49,12 +49,28 @@ setSelector = "#appslist" # function that writes the list order to session setOrder = -> + setKey '_appsListOrder', $(setSelector).sortable("toArray").join() + +removeOidcConsent = (partner) -> + r = new RegExp partner, 'g' + datas['oidcConsents'] = datas['oidcConsents'].replace(r,'').replace(',+',',') + setKey '_oidcConnectedRP', datas['oidcConsents'] + $(this).text() + +setKey = (key,val) -> $.ajax - type: "PUT" - url: datas['scriptname'] + '/mysession/persistent' - data: - _appsListOrder: $(setSelector).sortable("toArray").join() + type: "GET" + url: datas['scriptname'] + '/mysession/?gettoken' dataType: 'json' + success: (data) -> + d = + token: data.token + d[key] = val + $.ajax + type: "PUT" + url: datas['scriptname'] + '/mysession/persistent' + dataType: 'json' + data: d # function that restores the list order from session restoreOrder = -> @@ -250,3 +266,5 @@ $(document).ready -> s = new Date($(this).attr("val")*1000) $(this).text s.toLocaleString() + $('.oidcConsent').on 'click', () -> + removeOidcConsent $(this).attr 'partner' diff --git a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js index bc1fab8b2..ab023b339 100644 --- a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js +++ b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js @@ -5,7 +5,7 @@ LemonLDAP::NG Portal jQuery scripts */ (function() { - var datas, getCookie, getValues, isHiddenFormValueSet, ping, restoreOrder, setCookie, setOrder, setSelector, translate, translatePage, translationFields, + var datas, getCookie, getValues, isHiddenFormValueSet, ping, removeOidcConsent, restoreOrder, setCookie, setKey, setOrder, setSelector, translate, translatePage, translationFields, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; translationFields = {}; @@ -71,13 +71,35 @@ LemonLDAP::NG Portal jQuery scripts setSelector = "#appslist"; setOrder = function() { + return setKey('_appsListOrder', $(setSelector).sortable("toArray").join()); + }; + + removeOidcConsent = function(partner) { + var r; + r = new RegExp(partner, 'g'); + datas['oidcConsents'] = datas['oidcConsents'].replace(r, '').replace(',+', ','); + setKey('_oidcConnectedRP', datas['oidcConsents']); + return $(this).text(); + }; + + setKey = function(key, val) { return $.ajax({ - type: "PUT", - url: datas['scriptname'] + '/mysession/persistent', - data: { - _appsListOrder: $(setSelector).sortable("toArray").join() - }, - dataType: 'json' + type: "GET", + url: datas['scriptname'] + '/mysession/?gettoken', + dataType: 'json', + success: function(data) { + var d; + d = { + token: data.token + }; + d[key] = val; + return $.ajax({ + type: "PUT", + url: datas['scriptname'] + '/mysession/persistent', + dataType: 'json', + data: d + }); + } }); }; @@ -261,11 +283,14 @@ LemonLDAP::NG Portal jQuery scripts if (datas['pingInterval'] && datas['pingInterval'] > 0) { window.setTimeout(ping, datas['pingInterval']); } - return $(".localeDate").each(function() { + $(".localeDate").each(function() { var s; s = new Date($(this).attr("val") * 1000); return $(this).text(s.toLocaleString()); }); + return $('.oidcConsent').on('click', function() { + return removeOidcConsent($(this).attr('partner')); + }); }); }).call(this); diff --git a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js index 8b0d3a23b..a65a91e38 100644 --- a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js +++ b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js @@ -1 +1 @@ -(function(){var e,g,d,a,k,j,m,i,f,b,l,c,h=[].indexOf||function(p){for(var o=0,n=this.length;o div.category",update:function(){return i()}});j();$("div.message").fadeIn("slow");$("input[name=timezone]").val(-(new Date().getTimezoneOffset()/60));q=$("#menu").tabs({active:0});A=$('#menu a[href="#'+e.displaytab+'"]').parent().index();if(A<0){A=0}q.tabs("option","active",A);F=$("#authMenu").tabs({active:0});if(e.choicetab){F.tabs("option","active",$('#authMenu a[href="#'+e.choicetab+'"]').parent().index())}if(e.login){$("input[type=password]:first").focus()}else{$("input[type!=hidden]:first").focus()}if(e.newwindow){$("#appslist a").attr("target","_blank")}if($("p.removeOther").length){E=$("form.login").attr("action");p=$("form.login").attr("method");C="";if(E.indexOf("?")!==-1){E.substring(0,E.indexOf("?"))+"?"}else{C=E+"?"}$("form.login input[type=hidden]").each(function(J){return C+="&"+$(this).attr("name")+"="+$(this).val()});s=$("p.removeOther a").attr("href")+"&method="+p+"&url="+btoa(C);$("p.removeOther a").attr("href",s)}I=g("llnglanguage");if(!I){if(navigator){x=[];w=[];n=[navigator.language];if(navigator.languages){n=navigator.languages}r=window.availableLanguages;for(G=0,H=r.length;G ';for(B=0,u=n.length;B '}$("#languages").html(y);$(".langicon").on("click",function(){I=$(this).attr("title");m("llnglanguage",I);return l(I)});if(e.pingInterval&&e.pingInterval>0){window.setTimeout(k,e.pingInterval)}return $(".localeDate").each(function(){var J;J=new Date($(this).attr("val")*1000);return $(this).text(J.toLocaleString())})})}).call(this); \ No newline at end of file +(function(){var f,i,e,b,m,h,l,o,a,k,g,c,n,d,j=[].indexOf||function(r){for(var q=0,p=this.length;q div.category",update:function(){return k()}});l();$("div.message").fadeIn("slow");$("input[name=timezone]").val(-(new Date().getTimezoneOffset()/60));s=$("#menu").tabs({active:0});C=$('#menu a[href="#'+f.displaytab+'"]').parent().index();if(C<0){C=0}s.tabs("option","active",C);H=$("#authMenu").tabs({active:0});if(f.choicetab){H.tabs("option","active",$('#authMenu a[href="#'+f.choicetab+'"]').parent().index())}if(f.login){$("input[type=password]:first").focus()}else{$("input[type!=hidden]:first").focus()}if(f.newwindow){$("#appslist a").attr("target","_blank")}if($("p.removeOther").length){G=$("form.login").attr("action");r=$("form.login").attr("method");E="";if(G.indexOf("?")!==-1){G.substring(0,G.indexOf("?"))+"?"}else{E=G+"?"}$("form.login input[type=hidden]").each(function(L){return E+="&"+$(this).attr("name")+"="+$(this).val()});u=$("p.removeOther a").attr("href")+"&method="+r+"&url="+btoa(E);$("p.removeOther a").attr("href",u)}K=i("llnglanguage");if(!K){if(navigator){z=[];y=[];p=[navigator.language];if(navigator.languages){p=navigator.languages}t=window.availableLanguages;for(I=0,J=t.length;I ';for(D=0,w=p.length;D '}$("#languages").html(A);$(".langicon").on("click",function(){K=$(this).attr("title");o("llnglanguage",K);return n(K)});if(f.pingInterval&&f.pingInterval>0){window.setTimeout(m,f.pingInterval)}$(".localeDate").each(function(){var L;L=new Date($(this).attr("val")*1000);return $(this).text(L.toLocaleString())});return $(".oidcConsent").on("click",function(){return h($(this).attr("partner"))})})}).call(this); \ No newline at end of file