diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm index b7956a989..ec3d4657b 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm @@ -242,10 +242,10 @@ sub checkMaintenanceMode { # @param $cond optional Function granting access # @return True if the user is granted to access to the current URL sub grant { - my ( $class, $uri, $cond ) = @_; + my ( $class, $uri, $cond, $vhost ) = @_; return &{$cond}() if ($cond); - my $vhost = $class->resolveAlias; + $vhost ||= $class->resolveAlias; for ( my $i = 0 ; $i < $class->tsv->{locationCount}->{$vhost} ; $i++ ) { if ( $uri =~ $class->tsv->{locationRegexp}->{$vhost}->[$i] ) { $class->lmLog( 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 ccfee766c..a2c354896 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -76,17 +76,18 @@ sub display { else { $skinfile = 'menu'; + #utf8::decode($auth_user); %templateParams = ( - AUTH_USER => $req->{sessionInfo}->{ $self->conf->{portalUserAttr} }, - NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow}, - LOGOUT_URL => $self->conf->{portal} . "?logout=1", - APPSLIST_ORDER => $req->{sessionInfo}->{'appsListOrder'}, - PING => $self->conf->{portalPingInterval}, + AUTH_USER => + $req->{sessionInfo}->{ $self->conf->{portalUserAttr} }, + NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow}, + LOGOUT_URL => $self->conf->{portal} . "?logout=1", + APPSLIST_ORDER => $req->{sessionInfo}->{'appsListOrder'}, + PING => $self->conf->{portalPingInterval}, $self->menu->params($req), ); - } } @@ -310,7 +311,7 @@ sub display { } $self->lmLog( "Skin returned: $skinfile", 'debug' ); - return ( $skinfile, \%templateParams); + return ( $skinfile, \%templateParams ); } @@ -410,4 +411,40 @@ sub getCustomTemplateParameters { return $customTplParams; } +# Build an HTML array to display sessions +# @param $sessions Array ref of hash ref containing sessions datas +# @param $title Title of the array +# @param $displayUser To display "User" column +# @param $displaError To display "Error" column +# @return HTML string +sub mkSessionArray { + my ( $self, $sessions, $title, $displayUser, $displayError ) = @_; + + return "" unless ( ref $sessions eq "ARRAY" and @$sessions ); + + my $tmp = $title ? "

$title

" : ""; + $tmp .= + '' + . ( $displayUser ? '' : '' ) + . ''; + $tmp .= "" + foreach ( keys %{ $self->conf->{sessionDataToRemember} } ); + $tmp .= '' if ($displayError); + $tmp .= ''; + + foreach my $session (@$sessions) { + $tmp .= ""; + $tmp .= "" if ($displayUser); + $tmp .= +""; + $tmp .= ""; + $tmp .= "" + foreach ( keys %{ $self->conf->{sessionDataToRemember} } ); + $tmp .= "" if ($displayError); + $tmp .= ""; + } + $tmp .= '
UserDateIP address" . $self->conf->{sessionDataToRemember}->{$_} . "Error message
$session->{user}$session->{ipAddr}" . ( $session->{$_} || "" ) . "$session->{error}
'; + return $tmp; +} + 1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm index a533bce5a..7d6fd49a9 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm @@ -19,6 +19,7 @@ use Regexp::Assemble; # Configuration storage has localConfig => ( is => 'rw', default => sub { {} } ); has conf => ( is => 'rw', default => sub { {} } ); +has menu => ( is => 'rw', default => sub { {} } ); # Sub modules has _authentication => ( is => 'rw' ); @@ -74,7 +75,7 @@ sub init { # "/" ->addUnauthRoute( '*', 'login', ['GET'] ) ->addUnauthRoute( '*', 'postLogin', ['POST'] ) - ->addAuthRoute( '*', 'authenticatedRequest', ['GET'] ) + ->addAuthRoute( '*', 'authenticatedRequest', ['GET'] ) ->addAuthRoute( '*', 'postAuthenticatedRequest', ['POST'] ) # Core REST API @@ -226,7 +227,7 @@ sub reloadConf { $self->loadPlugin($plugin) or return 0; } - $self->menu = $self->loadModule('::Main::Menu'); + $self->menu( $self->loadModule('::Main::Menu') ); 1; } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm index 5f138c414..3b2d96e29 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm @@ -15,8 +15,11 @@ has menuModules => ( my %res; foreach (qw(Appslist ChangePassword LoginHistory Logout)) { my $cond = $conf->{"portalDisplay$_"} // 1; - $_[0]->p->lmLog( "Evaluate condition $cond for module $_", 'debug' ); - $res{$_} = $_[0]->{p}->HANDLER->tsv->{jail}->jail_reval($cond); + $_[0] + ->p->lmLog( "Evaluate condition $cond for module $_", 'debug' ); + my $tmp = + $_[0]->{p}->HANDLER->tsv->{jail}->jail_reval("sub{return $cond}"); + $res{$_} = $tmp if ($tmp); } return \%res; } @@ -42,9 +45,6 @@ sub params { # Tab to display # Get the tab URL parameter - $res{DISPLAY_TAB} = - scalar( grep /^(password|logout|loginHistory)$/, $req->param("tab") ) - || "applist"; # Force password tab in case of password error if ( @@ -73,12 +73,15 @@ sub params { # else calculate modules to display else { - $res{DISPLAY_MODULES} = $self->displayModules($req); + $res{DISPLAY_TAB} = + scalar( grep /^(password|logout|loginHistory)$/, $req->param("tab") ) + || "applist"; } + $res{DISPLAY_MODULES} = $self->displayModules($req); $res{AUTH_ERROR_TYPE} = $req->error_type( $res{AUTH_ERROR} = $req->menuError ); - return \%res; + return %res; } ## @method arrayref displayModules() @@ -100,11 +103,11 @@ sub displayModules { } elsif ( $module eq 'LoginHistory' ) { $moduleHash->{'SUCCESS_LOGIN'} = - $self->mkSessionArray( + $self->p->mkSessionArray( $req->{sessionInfo}->{loginHistory}->{successLogin}, "", 0, 0 ); $moduleHash->{'FAILED_LOGIN'} = - $self->mkSessionArray( + $self->p->mkSessionArray( $req->{sessionInfo}->{loginHistory}->{failedLogin}, "", 0, 1 ); } @@ -172,7 +175,7 @@ sub _buildCategoryHash { next if $catkey =~ /(type|options|catname)/; if ( $cathash->{$catkey}->{type} eq "category" ) { push @$categories, - $self->_buildCategoryHash( $catkey, $cathash->{$catkey}, + $self->_buildCategoryHash( $req, $catkey, $cathash->{$catkey}, $catlevel + 1 ); } } @@ -390,7 +393,7 @@ sub _filter { } # Filter hash - $self->_filterHash($filteredHash); + $self->_filterHash( $req, $filteredHash ); # Hide empty categories $self->_isCategoryEmpty($filteredHash); @@ -403,36 +406,36 @@ sub _filter { # @param $apphash Menu elements # @return filtered hash sub _filterHash { - my $self = shift; - my ($apphash) = @_; - my $key; - my $appkey; + my ( $self, $req, $apphash ) = @_; - foreach $key ( keys %$apphash ) { + foreach my $key ( keys %$apphash ) { next if $key =~ /(type|options|catname)/; if ( $apphash->{$key}->{type} and $apphash->{$key}->{type} eq "category" ) { # Filter the category - $self->_filterHash( $apphash->{$key} ); + $self->_filterHash( $req, $apphash->{$key} ); } if ( $apphash->{$key}->{type} and $apphash->{$key}->{type} eq "application" ) { # Find sub applications and filter them - foreach $appkey ( keys %{ $apphash->{$key} } ) { + foreach my $appkey ( keys %{ $apphash->{$key} } ) { next if $appkey =~ /(type|options|catname)/; # We have sub elements, so we filter them - $self->_filterHash( $apphash->{$key} ); + $self->_filterHash( $req, $apphash->{$key} ); } # Check rights my $appdisplay = $apphash->{$key}->{options}->{display} || "auto"; - my $appuri = $apphash->{$key}->{options}->{uri}; + my ( $vhost, $appuri ) = + $apphash->{$key}->{options}->{uri} =~ m#^https?://([^/]*)(.*)#; + $vhost =~ s/:\d+$//; + $appuri ||= '/'; # Remove if display is "no" or "off" delete $apphash->{$key} and next if ( $appdisplay =~ /^(no|off)$/ ); @@ -441,7 +444,8 @@ sub _filterHash { next if ( $appdisplay =~ /^(yes|on)$/ ); # Check grant function if display is "auto" (this is the default) - delete $apphash->{$key} unless ( $self->_grant($appuri) ); + delete $apphash->{$key} + unless ( $self->p->HANDLER->grant( $appuri, undef, $vhost ) ); next; } } diff --git a/lemonldap-ng-portal/site/static/languages/en.json b/lemonldap-ng-portal/site/static/languages/en.json index f36d5f7d8..b9861ec31 100644 --- a/lemonldap-ng-portal/site/static/languages/en.json +++ b/lemonldap-ng-portal/site/static/languages/en.json @@ -80,9 +80,6 @@ PE77:"You have to type the captcha", PE78:"Please enter your information", PE79:"An information is missing", PE80:"This address is already used", -PM0:"User", -PM1:"Date", -PM2:"IP address", PM3:"The following sessions have been closed", PM4:"Other active sessions", PM5:"Remove other sessions", @@ -101,7 +98,6 @@ PM17:"Update Common Domain Cookie", PM18:"Parameter %s requested for federation isn't available", PM19:"Data usage policy is available at", PM20:"Do you agree to provide the following parameters?", -PM21:"Error Message", PM22:"Your last logins", PM23:"Your last failed logins", PM24:"The application %s would like to know:", @@ -138,9 +134,11 @@ connectedAs:"Connected as", continue:"Continue", createAccount:"Create an account", currentPwd:"Current password", +date:"Date", enterCred:"Please enter your credentials", enterOpenIDLogin:"Please enter your OpenID login", enterYubikey:"Please use your Yubikey", +errorMsg:"Error Message", firstName:"First name", forgotPwd:"Forgot your password?", generatePwd:"Generate the password automatically", @@ -150,6 +148,7 @@ gplSoft:"free software covered by the GPL license", hello:"Hello", imSure:"I'm sure", info:"Information", +ipAddr:"IP address", lastFailedLogins:"Last failed logins", lastLogins:"Last logins", lastName:"Last name", @@ -188,6 +187,7 @@ serverError:"Error occurs on the server", serviceProvidedBy:"Service provided by", SSOSessionInactive:"SSO session inactive", submit:"Submit", +user:"User", useYubikey:"use your Yubikey", wait:"Wait", warning:"Warning", diff --git a/lemonldap-ng-portal/site/static/languages/fr.json b/lemonldap-ng-portal/site/static/languages/fr.json index 1aa32ea98..2518bfc1f 100644 --- a/lemonldap-ng-portal/site/static/languages/fr.json +++ b/lemonldap-ng-portal/site/static/languages/fr.json @@ -80,9 +80,6 @@ PE77:"Vous devez saisir le captcha", PE78:"Merci de saisir vos informations", PE79:"Une information est manquante", PE80:"Cette adresse est déjà utilisée", -PM0:"Utilisateur", -PM1:"Date", -PM2:"Adresse IP", PM3:"Les sessions suivantes ont été fermées", PM4:"Autres sessions ouvertes", PM5:"Fermer les autres sessions", @@ -101,7 +98,6 @@ PM17:"Mise à jour du cookie de domaine commun", PM18:"Le paramètre %s exigé pour la fédération n'est pas disponible", PM19:"La politique d'utilisation des données est disponible ici", PM20:"Consentez-vous à communiquer les paramètres suivants ?", -PM21:"Message d'erreur", PM22:"Vos dernières connexions", PM23:"Vos dernières connexions refusées", PM24:"L'application %s voudrait connaître :", @@ -138,9 +134,11 @@ connect:"Se connecter", continue:"Continuer", createAccount:"Créer un compte", currentPwd:"Mot de passe actuel", +date:"Date", enterCred:"Merci de vous authentifier", enterOpenIDLogin:"Entrez votre identifiant OpenID", enterYubikey:"Utilisez votre Yubikey", +errorMsg:"Message d'erreur", firstName:"Prénom", forgotPwd:"Mot de passe oublié ?", generatePwd:"Générer le mot de passe automatiquement", @@ -150,6 +148,7 @@ gplSoft:"logiciel libre protégé par la licence GPL", hello:"Bonjour", imSure:"Je suis sûr", info:"Information", +ipAddr:"Adresse IP", lastFailedLogins:"Dernières connexions refusées", lastLogins:"Dernières connexions", lastName:"Nom", @@ -188,6 +187,7 @@ serverError:"Une erreur est survenue sur le serveur", serviceProvidedBy:"Ce service est fourni par", SSOSessionInactive:"Session SSO inactive", submit:"Envoyer", +user:"Utilisateur", useYubikey:"utilisez votre Yubikey", wait:"Attendre", warning:"Attention",