Merge branch 'favapps' into 'master'
Favapps Closes #1689 See merge request lemonldap-ng/lemonldap-ng!74
This commit is contained in:
commit
c233ef37ef
12
COPYING
12
COPYING
|
@ -99,6 +99,18 @@ License: CC-3
|
|||
Comment: This work, "sfa_manager.png", is a derivative of
|
||||
"Noun project 1162.svg" by Christopher T. Howlett, under CC-BY-3.0.
|
||||
|
||||
Files: lemonldap-ng-portal/site/htdocs/static/common/icons/star0.png
|
||||
Copyright: Christophe Maudoux <chrmdx@gmail.com>
|
||||
License: CC-3
|
||||
Comment: This work, "star0.png", is a derivative of
|
||||
"Silver star with red border.png" by ANGELUS, under CC-BYSA-3.0.
|
||||
|
||||
Files: lemonldap-ng-portal/site/htdocs/static/common/icons/star1.png
|
||||
Copyright: Christophe Maudoux <chrmdx@gmail.com>
|
||||
License: CC-3
|
||||
Comment: This work, "star1.png", is a derivative of
|
||||
"Golden star with red border.png" by ANGELUS, under CC-BYSA-3.0.
|
||||
|
||||
Files: lemonldap-ng-portal/site/htdocs/static/common/modules/CustomAuth.png
|
||||
Copyright: Christophe Maudoux <chrmdx@gmail.com>
|
||||
License: CC-3
|
||||
|
|
|
@ -57,6 +57,7 @@ sub defaultValues {
|
|||
'facebookExportedVars' => {},
|
||||
'facebookUserField' => 'id',
|
||||
'failedLoginNumber' => 5,
|
||||
'favAppsMaxNumber' => 3,
|
||||
'formTimeout' => 120,
|
||||
'globalStorage' => 'Apache::Session::File',
|
||||
'globalStorageOptions' => {
|
||||
|
@ -190,6 +191,7 @@ sub defaultValues {
|
|||
'portalCheckLogins' => 1,
|
||||
'portalDisplayAppslist' => 1,
|
||||
'portalDisplayChangePassword' => '$_auth =~ /^(LDAP|DBI|Demo)$/',
|
||||
'portalDisplayFavApps' => 1,
|
||||
'portalDisplayLoginHistory' => 1,
|
||||
'portalDisplayLogout' => 1,
|
||||
'portalDisplayOidcConsents' => '$_oidcConnectedRP',
|
||||
|
|
|
@ -1147,6 +1147,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
'default' => 5,
|
||||
'type' => 'int'
|
||||
},
|
||||
'favAppsMaxNumber' => {
|
||||
'default' => 3,
|
||||
'type' => 'int'
|
||||
},
|
||||
'formTimeout' => {
|
||||
'default' => 120,
|
||||
'type' => 'int'
|
||||
|
@ -2261,6 +2265,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => '$_auth =~ /^(LDAP|DBI|Demo)$/',
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'portalDisplayFavApps' => {
|
||||
'default' => 1,
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'portalDisplayLoginHistory' => {
|
||||
'default' => 1,
|
||||
'type' => 'boolOrExpr'
|
||||
|
|
|
@ -446,6 +446,18 @@ sub attributes {
|
|||
documentation => 'Display session empty values',
|
||||
flags => 'p',
|
||||
},
|
||||
favAppsMaxNumber => {
|
||||
default => 3,
|
||||
type => 'int',
|
||||
documentation => 'Maximum favorite Apps number',
|
||||
flags => 'p',
|
||||
},
|
||||
portalDisplayFavApps => {
|
||||
type => 'boolOrExpr',
|
||||
default => 1,
|
||||
documentation => 'Display favorite applications tab in portal',
|
||||
flags => 'p',
|
||||
},
|
||||
impersonationMergeSSOgroups => {
|
||||
default => 0,
|
||||
type => 'bool',
|
||||
|
|
|
@ -43,6 +43,15 @@ sub tree {
|
|||
'portalDisplayAppslist',
|
||||
'portalDisplayLoginHistory',
|
||||
'portalDisplayOidcConsents',
|
||||
{
|
||||
title => 'favApps',
|
||||
help => 'favapps.html',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'portalDisplayFavApps',
|
||||
'favAppsMaxNumber',
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
'applicationList'
|
||||
|
|
|
@ -263,6 +263,8 @@
|
|||
"facebookParams":"معاييرفاسيبوك",
|
||||
"facebookUserField":"Field containing user identifier",
|
||||
"failedLoginNumber":"عدد عمليات تسجيل الدخول الفاشلة المسجلة",
|
||||
"favApps":"Favorite Apps",
|
||||
"favAppsMaxNumber":"Max number of favorite Apps",
|
||||
"fileToUpload":"الملف الذي ستحمله",
|
||||
"forbidden":"لست مخولا بعرض هذه الصفحة",
|
||||
"forceSave":"فرض الحفظ",
|
||||
|
@ -612,6 +614,7 @@
|
|||
"portalCustomization":"التخصيص",
|
||||
"portalDisplayAppslist":"قائمة التطبيقات",
|
||||
"portalDisplayChangePassword":"تغيير كلمة المرور",
|
||||
"portalDisplayFavApps":"Activation rule",
|
||||
"portalDisplayLoginHistory":"سجل تسجيل الدخول",
|
||||
"portalDisplayLogout":"تسجيل الخروج",
|
||||
"portalDisplayOidcConsents":"OIDC Consents",
|
||||
|
|
|
@ -263,6 +263,8 @@
|
|||
"facebookParams":"Facebook parameters",
|
||||
"facebookUserField":"Field containing user identifier",
|
||||
"failedLoginNumber":"Number of registered failed logins",
|
||||
"favApps":"Favorite Apps",
|
||||
"favAppsMaxNumber":"Max number of favorite Apps",
|
||||
"fileToUpload":"File to upload",
|
||||
"forbidden":"You're not authorized to show this page",
|
||||
"forceSave":"Force save",
|
||||
|
@ -612,6 +614,7 @@
|
|||
"portalCustomization":"Customization",
|
||||
"portalDisplayAppslist":"Applications list",
|
||||
"portalDisplayChangePassword":"Password change",
|
||||
"portalDisplayFavApps":"Activation rule",
|
||||
"portalDisplayLoginHistory":"Login History",
|
||||
"portalDisplayLogout":"Logout",
|
||||
"portalDisplayOidcConsents":"OIDC Consents",
|
||||
|
|
|
@ -263,6 +263,8 @@
|
|||
"facebookParams":"Facebook parameters",
|
||||
"facebookUserField":"Field containing user identifier",
|
||||
"failedLoginNumber":"Number of registered failed logins",
|
||||
"favApps":"Favorite Apps",
|
||||
"favAppsMaxNumber":"Max number of favorite Apps",
|
||||
"fileToUpload":"File to upload",
|
||||
"forbidden":"You're not authorized to show this page",
|
||||
"forceSave":"Force save",
|
||||
|
@ -611,6 +613,7 @@
|
|||
"portalCheckLogins":"Check last logins",
|
||||
"portalCustomization":"Customization",
|
||||
"portalDisplayAppslist":"Applications list",
|
||||
"portalDisplayFavApps":"Activation rule",
|
||||
"portalDisplayChangePassword":"Password change",
|
||||
"portalDisplayLoginHistory":"Login History",
|
||||
"portalDisplayLogout":"Logout",
|
||||
|
|
|
@ -263,6 +263,8 @@
|
|||
"facebookParams":"Paramètres Facebook",
|
||||
"facebookUserField":"Champ contenant l'identifiant de l'utilisateur",
|
||||
"failedLoginNumber":"Nombre d'échecs de connexion mémorisés",
|
||||
"favApps":"Applications favorites",
|
||||
"favAppsMaxNumber":"Nombre maximum d'applications",
|
||||
"fileToUpload":"Fichier à télécharger",
|
||||
"forbidden":"Vous n'êtes pas autorisé à visualiser cette page",
|
||||
"forceSave":"Forcer la sauvegarde",
|
||||
|
@ -611,6 +613,7 @@
|
|||
"portalCheckLogins":"Vérifier l'historique",
|
||||
"portalCustomization":"Personnalisation",
|
||||
"portalDisplayAppslist":"Liste des applications",
|
||||
"portalDisplayFavApps":"Règle d'utilisation",
|
||||
"portalDisplayChangePassword":"Changement de mot de passe",
|
||||
"portalDisplayLoginHistory":"Historique des connexions",
|
||||
"portalDisplayLogout":"Déconnexion",
|
||||
|
|
|
@ -263,6 +263,8 @@
|
|||
"facebookParams":"Parametri di Facebook",
|
||||
"facebookUserField":"Campo contenente l'identificatore dell'utente",
|
||||
"failedLoginNumber":"Numero di login registrati non riusciti",
|
||||
"favApps":"Favorite Apps",
|
||||
"favAppsMaxNumber":"Max number of favorite Apps",
|
||||
"fileToUpload":"File da caricare",
|
||||
"forbidden":"Non sei autorizzato a mostrare questa pagina",
|
||||
"forceSave":"Forza salvataggio",
|
||||
|
@ -611,6 +613,7 @@
|
|||
"portalCheckLogins":"Controllare ultimi accessi",
|
||||
"portalCustomization":"Personalizzazione",
|
||||
"portalDisplayAppslist":"Lista delle applicazioni",
|
||||
"portalDisplayFavApps":"Activation rule",
|
||||
"portalDisplayChangePassword":"Cambio password",
|
||||
"portalDisplayLoginHistory":"Cronologia login",
|
||||
"portalDisplayLogout":"Logout",
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
"authChoiceParam":"Tham số URL",
|
||||
"authentication":"Mô đun xác thực",
|
||||
"authenticationNeeded":"Xác thực cần thiết",
|
||||
"portalDisplayFavApps":"Activation rule",
|
||||
"authenticationLevel":"Mức xác thực",
|
||||
"authenticationTitle":"Xác thực",
|
||||
"AuthLDAPFilter":"Bộ lọc xác thực",
|
||||
|
@ -263,6 +264,8 @@
|
|||
"facebookParams":"Tham số Facebook",
|
||||
"facebookUserField":"Field containing user identifier",
|
||||
"failedLoginNumber":"Số lượt đăng nhập thất bại",
|
||||
"favApps":"Favorite Apps",
|
||||
"favAppsMaxNumber":"Max number of favorite Apps",
|
||||
"fileToUpload":"Tập tin để tải lên",
|
||||
"forbidden":"Bạn không được ủy quyền để hiển thị trang này",
|
||||
"forceSave":"Bắt buộc lưu",
|
||||
|
|
|
@ -263,6 +263,8 @@
|
|||
"facebookParams":"Facebook 参数",
|
||||
"facebookUserField":"Field containing user identifier",
|
||||
"failedLoginNumber":"Number of registered failed logins",
|
||||
"favApps":"Favorite Apps",
|
||||
"favAppsMaxNumber":"Max number of favorite Apps",
|
||||
"fileToUpload":"上传的文件",
|
||||
"forbidden":"You're not authorized to show this page",
|
||||
"forceSave":"强制保存",
|
||||
|
@ -611,6 +613,7 @@
|
|||
"portalCheckLogins":"Check last logins",
|
||||
"portalCustomization":"Customization",
|
||||
"portalDisplayAppslist":"Applications list",
|
||||
"portalDisplayFavApps":"Activation rule",
|
||||
"portalDisplayChangePassword":"Password change",
|
||||
"portalDisplayLoginHistory":"Login History",
|
||||
"portalDisplayLogout":"Logout",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -102,6 +102,7 @@ lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm
|
|||
lib/Lemonldap/NG/Portal/Plugins/CDA.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/CheckState.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/CheckUser.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/FavApps.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/ForceAuthn.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/History.pm
|
||||
|
@ -148,6 +149,7 @@ scripts/llngDeleteSession
|
|||
site/coffee/2fregistration.coffee
|
||||
site/coffee/autoRenew.coffee
|
||||
site/coffee/confirm.coffee
|
||||
site/coffee/favapps.coffee
|
||||
site/coffee/idpchoice.coffee
|
||||
site/coffee/info.coffee
|
||||
site/coffee/kerberos.coffee
|
||||
|
@ -256,6 +258,8 @@ site/htdocs/static/common/icons/key.png
|
|||
site/htdocs/static/common/icons/oidc.png
|
||||
site/htdocs/static/common/icons/ok.png
|
||||
site/htdocs/static/common/icons/sfa_manager.png
|
||||
site/htdocs/static/common/icons/star0.png
|
||||
site/htdocs/static/common/icons/star1.png
|
||||
site/htdocs/static/common/icons/vcard_edit.png
|
||||
site/htdocs/static/common/icons/warning.png
|
||||
site/htdocs/static/common/it.png
|
||||
|
@ -265,6 +269,8 @@ site/htdocs/static/common/js/autoRenew.js
|
|||
site/htdocs/static/common/js/autoRenew.min.js
|
||||
site/htdocs/static/common/js/confirm.js
|
||||
site/htdocs/static/common/js/confirm.min.js
|
||||
site/htdocs/static/common/js/favapps.js
|
||||
site/htdocs/static/common/js/favapps.min.js
|
||||
site/htdocs/static/common/js/idpchoice.js
|
||||
site/htdocs/static/common/js/idpchoice.min.js
|
||||
site/htdocs/static/common/js/info.js
|
||||
|
@ -399,7 +405,6 @@ site/templates/common/mail_register_done.tpl
|
|||
site/templates/common/notification.xsl
|
||||
site/templates/common/notifinclude.tpl
|
||||
site/templates/common/oidc_checksession.tpl
|
||||
site/templates/common/redirect.tpl
|
||||
site/templates/common/registerBrowser.tpl
|
||||
site/templates/common/script.tpl
|
||||
t/01-AuthDemo.t
|
||||
|
@ -518,6 +523,7 @@ t/67-CheckUser-with-token.t
|
|||
t/67-CheckUser.t
|
||||
t/68-Impersonation-with-merge.t
|
||||
t/68-Impersonation.t
|
||||
t/69-FavApps.t
|
||||
t/70-2F-TOTP-with-History.t
|
||||
t/70-2F-TOTP.t
|
||||
t/70-2F-TOTP_8.t
|
||||
|
|
|
@ -1168,17 +1168,17 @@ sub createJWT {
|
|||
|
||||
my $digest;
|
||||
|
||||
if ( $alg eq "HS256" ) {
|
||||
if ( $alg eq "HS256" && $client_secret ) {
|
||||
$digest = hmac_sha256_base64( $jwt_header . "." . $jwt_payload,
|
||||
$client_secret );
|
||||
}
|
||||
|
||||
if ( $alg eq "HS384" ) {
|
||||
if ( $alg eq "HS384" && $client_secret ) {
|
||||
$digest = hmac_sha384_base64( $jwt_header . "." . $jwt_payload,
|
||||
$client_secret );
|
||||
}
|
||||
|
||||
if ( $alg eq "HS512" ) {
|
||||
if ( $alg eq "HS512" && $client_secret ) {
|
||||
$digest = hmac_sha512_base64( $jwt_header . "." . $jwt_payload,
|
||||
$client_secret );
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use JSON;
|
|||
use Data::Dumper;
|
||||
|
||||
has skinRules => ( is => 'rw' );
|
||||
has favAppsRule => ( is => 'rw', default => sub { 1 } );
|
||||
|
||||
sub displayInit {
|
||||
my ($self) = @_;
|
||||
|
@ -29,6 +30,18 @@ sub displayInit {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Parse FavApps activation rule
|
||||
$self->logger->debug(
|
||||
"FavApps activation rule -> " . $self->conf->{portalDisplayFavApps} );
|
||||
my $rule =
|
||||
HANDLER->buildSub( HANDLER->substitute( $self->conf->{portalDisplayFavApps} ) );
|
||||
unless ($rule) {
|
||||
$self->error(
|
||||
"Bad FavApps activation rule -> " . HANDLER->tsv->{jail}->error );
|
||||
return 0;
|
||||
}
|
||||
$self->favAppsRule($rule);
|
||||
}
|
||||
|
||||
# Call portal process and set template parameters
|
||||
|
@ -206,6 +219,7 @@ sub display {
|
|||
PING => $self->conf->{portalPingInterval},
|
||||
REQUIRE_OLDPASSWORD => $self->conf->{portalRequireOldPassword},
|
||||
HIDE_OLDPASSWORD => 0,
|
||||
STARS => $self->favAppsRule->( $req, $req->userData ),
|
||||
$self->menu->params($req),
|
||||
(
|
||||
$req->data->{customScript}
|
||||
|
|
|
@ -5,6 +5,7 @@ package Lemonldap::NG::Portal::Main::Menu;
|
|||
use strict;
|
||||
use Mouse;
|
||||
use Clone 'clone';
|
||||
use JSON qw(from_json to_json);
|
||||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
|
@ -18,7 +19,10 @@ has menuModules => (
|
|||
builder => sub {
|
||||
my $conf = $_[0]->{conf};
|
||||
my @res;
|
||||
foreach (qw(Appslist ChangePassword LoginHistory OidcConsents Logout)) {
|
||||
foreach (
|
||||
qw(FavApps Appslist ChangePassword LoginHistory OidcConsents Logout)
|
||||
)
|
||||
{
|
||||
my $cond = $conf->{"portalDisplay$_"} // 1;
|
||||
$_[0]->p->logger->debug("Evaluate condition $cond for module $_");
|
||||
my $tmp =
|
||||
|
@ -59,9 +63,14 @@ sub params {
|
|||
my ( $self, $req ) = @_;
|
||||
$self->{conf}->{imgPath} ||= $self->{staticPrefix};
|
||||
my %res;
|
||||
my @defaultTabs = (qw/appslist password logout loginHistory oidcConsents/);
|
||||
my @defaultTabs =
|
||||
(qw/favApps appslist password logout loginHistory oidcConsents/);
|
||||
my @customTabs = split( /,\s*/, $self->{conf}->{customMenuTabs} || '' );
|
||||
|
||||
$res{DISPLAY_MODULES} = $self->displayModules($req);
|
||||
$res{AUTH_ERROR_TYPE} =
|
||||
$req->error_type( $res{AUTH_ERROR} = $req->menuError );
|
||||
|
||||
# Tab to display
|
||||
# Get the tab URL parameter
|
||||
|
||||
|
@ -101,14 +110,10 @@ sub params {
|
|||
$res{DISPLAY_TAB} = $req->param("tab");
|
||||
}
|
||||
else {
|
||||
$res{DISPLAY_TAB} = "appslist";
|
||||
$res{DISPLAY_TAB} = $res{DISPLAY_MODULES}->[0]->{FavApps} ? "favApps" : "appslist";
|
||||
}
|
||||
}
|
||||
|
||||
$res{DISPLAY_MODULES} = $self->displayModules($req);
|
||||
$res{AUTH_ERROR_TYPE} =
|
||||
$req->error_type( $res{AUTH_ERROR} = $req->menuError );
|
||||
|
||||
# Display menu 2fRegisters link only if at least a 2F device is registered
|
||||
$res{sfaManager} =
|
||||
$self->p->_sfEngine->display2fRegisters( $req, $req->userData );
|
||||
|
@ -123,30 +128,36 @@ sub params {
|
|||
sub displayModules {
|
||||
my ( $self, $req ) = @_;
|
||||
my $displayModules = [];
|
||||
my $favAppslistRef = $self->favAppslist($req);
|
||||
|
||||
# Foreach module, eval condition
|
||||
# Store module in result if condition is valid
|
||||
foreach my $module ( @{ $self->menuModules } ) {
|
||||
$self->logger->debug("Check if $module->[0] has to be displayed");
|
||||
|
||||
if ( $module->[1]->( $req, $req->sessionInfo ) ) {
|
||||
if ( $module->[1]->( $req, $req->userData ) ) {
|
||||
my $moduleHash = { $module->[0] => 1 };
|
||||
if ( $module->[0] eq 'Appslist' ) {
|
||||
$moduleHash->{'APPSLIST_LOOP'} = $self->appslist($req);
|
||||
if ( $module->[0] eq 'FavApps' ) {
|
||||
$moduleHash->{'FavApps'} = scalar @{$favAppslistRef};
|
||||
$moduleHash->{'FAVAPPS_LOOP'} = $favAppslistRef;
|
||||
}
|
||||
elsif ( $module->[0] eq 'Appslist' ) {
|
||||
$moduleHash->{'APPSLIST_LOOP'} =
|
||||
$self->appslist( $req, $favAppslistRef );
|
||||
}
|
||||
elsif ( $module->[0] eq 'LoginHistory' ) {
|
||||
$moduleHash->{'SUCCESS_LOGIN'} =
|
||||
$self->p->mkSessionArray(
|
||||
$req->{sessionInfo}->{_loginHistory}->{successLogin},
|
||||
$req->{userData}->{_loginHistory}->{successLogin},
|
||||
"", 0, 0 );
|
||||
$moduleHash->{'FAILED_LOGIN'} =
|
||||
$self->p->mkSessionArray(
|
||||
$req->{sessionInfo}->{_loginHistory}->{failedLogin},
|
||||
$req->{userData}->{_loginHistory}->{failedLogin},
|
||||
"", 0, 1 );
|
||||
}
|
||||
elsif ( $module->[0] eq 'OidcConsents' ) {
|
||||
$moduleHash->{'OIDC_CONSENTS'} =
|
||||
$self->p->mkOidcConsent( $req->sessionInfo );
|
||||
$self->p->mkOidcConsent( $req->userData );
|
||||
}
|
||||
push @$displayModules, $moduleHash;
|
||||
}
|
||||
|
@ -155,11 +166,40 @@ sub displayModules {
|
|||
return $displayModules;
|
||||
}
|
||||
|
||||
## @method arrayref favAppslist()
|
||||
# Returns favorite applications list as HTML::Template loop
|
||||
# @return applications list
|
||||
sub favAppslist {
|
||||
my ( $self, $req ) = @_;
|
||||
my $user = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
|
||||
# Read existing favorite Apps
|
||||
$self->logger->debug("Looking for favorite Apps...");
|
||||
my $_favApps;
|
||||
if ( $req->userData->{_favApps} ) {
|
||||
$_favApps = eval {
|
||||
from_json( $req->userData->{_favApps}, { allow_nonref => 1 } );
|
||||
};
|
||||
if ($@) {
|
||||
$self->logger->error("Corrupted session (_favApps): $@");
|
||||
return $self->p->sendError( $req, "Corrupted session", 500 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->logger->debug("No favorite Apps found");
|
||||
$_favApps = [];
|
||||
}
|
||||
$self->logger->debug(
|
||||
scalar @$_favApps . " favorite Apps found for $user" );
|
||||
|
||||
return $_favApps;
|
||||
}
|
||||
|
||||
## @method arrayref appslist()
|
||||
# Returns categories and applications list as HTML::Template loop
|
||||
# @return categories and applications list
|
||||
sub appslist {
|
||||
my ( $self, $req ) = @_;
|
||||
my ( $self, $req, $favAppslistRef ) = @_;
|
||||
my $appslist = [];
|
||||
|
||||
return $appslist unless defined $self->conf->{applicationList};
|
||||
|
@ -168,7 +208,8 @@ sub appslist {
|
|||
my $catlevel = 0;
|
||||
|
||||
my $applicationList = clone( $self->conf->{applicationList} );
|
||||
my $filteredList = $self->_filter( $req, $applicationList );
|
||||
my $filteredList =
|
||||
$self->_filter( $req, $applicationList, $favAppslistRef );
|
||||
push @$appslist,
|
||||
$self->_buildCategoryHash( $req, "", $filteredList, $catlevel );
|
||||
|
||||
|
@ -242,6 +283,7 @@ sub _buildApplicationHash {
|
|||
my $appuri = $apphash->{options}->{uri} || "";
|
||||
my $appdesc = $apphash->{options}->{description};
|
||||
my $applogo = $apphash->{options}->{logo};
|
||||
my $appIsFavApp = $apphash->{options}->{isFavApp} || "0";
|
||||
|
||||
# Detect sub applications
|
||||
my $subapphash;
|
||||
|
@ -267,6 +309,7 @@ sub _buildApplicationHash {
|
|||
appdesc => $appdesc,
|
||||
applogo => $applogo,
|
||||
appid => $appid,
|
||||
appisfav => $appIsFavApp,
|
||||
};
|
||||
$applicationHash->{applications} = $applications if $applications;
|
||||
return $applicationHash;
|
||||
|
@ -279,7 +322,7 @@ sub _buildApplicationHash {
|
|||
# @param $apphash Menu elements
|
||||
# @return filtered hash
|
||||
sub _filter {
|
||||
my ( $self, $req, $apphash ) = @_;
|
||||
my ( $self, $req, $apphash, $favAppslistRef ) = @_;
|
||||
my $filteredHash;
|
||||
my $key;
|
||||
|
||||
|
@ -289,7 +332,7 @@ sub _filter {
|
|||
}
|
||||
|
||||
# Filter hash
|
||||
$self->_filterHash( $req, $filteredHash );
|
||||
$self->_filterHash( $req, $filteredHash, $favAppslistRef );
|
||||
|
||||
# Hide empty categories
|
||||
$self->_isCategoryEmpty($filteredHash);
|
||||
|
@ -302,8 +345,7 @@ sub _filter {
|
|||
# @param $apphash Menu elements
|
||||
# @return filtered hash
|
||||
sub _filterHash {
|
||||
my ( $self, $req, $apphash ) = @_;
|
||||
|
||||
my ( $self, $req, $apphash, $favAppslistRef ) = @_;
|
||||
foreach my $key ( keys %$apphash ) {
|
||||
next if $key =~ /(type|options|catname)/;
|
||||
if ( $apphash->{$key}->{type}
|
||||
|
@ -311,7 +353,7 @@ sub _filterHash {
|
|||
{
|
||||
|
||||
# Filter the category
|
||||
$self->_filterHash( $req, $apphash->{$key} );
|
||||
$self->_filterHash( $req, $apphash->{$key}, $favAppslistRef );
|
||||
}
|
||||
if ( $apphash->{$key}->{type}
|
||||
and $apphash->{$key}->{type} eq "application" )
|
||||
|
@ -322,7 +364,17 @@ sub _filterHash {
|
|||
next if $appkey =~ /(type|options|catname)/;
|
||||
|
||||
# We have sub elements, so we filter them
|
||||
$self->_filterHash( $req, $apphash->{$key} );
|
||||
$self->_filterHash( $req, $apphash->{$key}, $favAppslistRef );
|
||||
}
|
||||
|
||||
# Check if app is marked as favorite
|
||||
my $uri = $apphash->{$key}->{options}->{uri};
|
||||
foreach (@$favAppslistRef) {
|
||||
if ( $_->{appuri} eq $uri ) {
|
||||
$apphash->{$key}->{options}->{isFavApp} = "1";
|
||||
$self->logger->debug("App $uri is marked as favorite");
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Check rights
|
||||
|
@ -348,7 +400,7 @@ sub _filterHash {
|
|||
if ( my $sub = $self->p->spRules->{$p} ) {
|
||||
eval {
|
||||
delete $apphash->{$key}
|
||||
unless ( $sub->( $req, $req->sessionInfo ) );
|
||||
unless ( $sub->( $req, $req->userData ) );
|
||||
};
|
||||
if ($@) {
|
||||
$self->logger->error("Partner rule $p returns: $@");
|
||||
|
@ -373,7 +425,7 @@ sub _filterHash {
|
|||
delete $apphash->{$key}
|
||||
unless (
|
||||
$self->p->HANDLER->grant(
|
||||
$req, $req->sessionInfo, $appuri, $cond, $vhost
|
||||
$req, $req->userData, $appuri, $cond, $vhost
|
||||
)
|
||||
);
|
||||
next;
|
||||
|
|
|
@ -27,6 +27,7 @@ our @pList = (
|
|||
portalForceAuthn => '::Plugins::ForceAuthn',
|
||||
checkUser => '::Plugins::CheckUser',
|
||||
impersonationRule => '::Plugins::Impersonation',
|
||||
portalDisplayFavApps => '::Plugins::FavApps',
|
||||
);
|
||||
|
||||
##@method list enabledPlugins
|
||||
|
|
|
@ -15,7 +15,6 @@ extends 'Lemonldap::NG::Portal::Main::Plugin',
|
|||
'Lemonldap::NG::Portal::Lib::_tokenRule';
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
has ott => (
|
||||
is => 'rw',
|
||||
lazy => 1,
|
||||
|
@ -54,8 +53,7 @@ sub init {
|
|||
return 1;
|
||||
}
|
||||
|
||||
# RUNNING METHOD
|
||||
|
||||
# RUNNING METHODS
|
||||
sub check {
|
||||
my ( $self, $req ) = @_;
|
||||
my ( $attrs, $array_attrs, $array_hdrs ) = ( {}, [], [] );
|
||||
|
|
213
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/FavApps.pm
Normal file
213
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/FavApps.pm
Normal file
|
@ -0,0 +1,213 @@
|
|||
package Lemonldap::NG::Portal::Plugins::FavApps;
|
||||
|
||||
use strict;
|
||||
use Mouse;
|
||||
use JSON qw(from_json to_json);
|
||||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
||||
|
||||
# INITIALIZATION
|
||||
has rule => ( is => 'rw', default => sub { 1 } );
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
my $hd = $self->p->HANDLER;
|
||||
|
||||
$self->addAuthRoute( favapps => 'register', ['POST'] );
|
||||
$self->addAuthRoute( favapps => 'read', ['GET'] );
|
||||
$self->addAuthRoute( favapps => 'reset', ['DELETE'] );
|
||||
|
||||
# Parse activation rule
|
||||
$self->logger->debug(
|
||||
"FavApps activation rule -> " . $self->conf->{portalDisplayFavApps} );
|
||||
my $rule =
|
||||
$hd->buildSub( $hd->substitute( $self->conf->{portalDisplayFavApps} ) );
|
||||
unless ($rule) {
|
||||
$self->error(
|
||||
"Bad FavApps activation rule -> " . $hd->tsv->{jail}->error );
|
||||
return 0;
|
||||
}
|
||||
$self->rule($rule);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# RUNNING METHODS
|
||||
sub register {
|
||||
my ( $self, $req ) = @_;
|
||||
my $user = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
|
||||
# Check activation rule
|
||||
unless ( $self->rule->( $req, $req->userData ) ) {
|
||||
$self->userLogger->warn(
|
||||
'FavApps requested by an unauthorized user ('
|
||||
. $req->{user}
|
||||
. ')' );
|
||||
$self->logger->debug('FavApps not authorized');
|
||||
return [
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/json',
|
||||
'Content-Length' => 11,
|
||||
],
|
||||
['{"error":0}']
|
||||
];
|
||||
}
|
||||
|
||||
my ( $uri, $result );
|
||||
unless ( $uri = $req->param('uri') ) {
|
||||
return $self->p->sendError( $req, 'Missing App. URI', 400 );
|
||||
}
|
||||
$self->logger->debug("Favorite application URI received : $uri");
|
||||
my $id = $req->param('id') || '';
|
||||
my $logo = $req->param('logo') || '';
|
||||
my $desc = $req->param('desc') || '';
|
||||
my $name = $req->param('name') || '';
|
||||
|
||||
# Read existing favorite Apps
|
||||
$self->logger->debug("Looking for $user favorite Apps...");
|
||||
my $_favApps;
|
||||
if ( $req->userData->{_favApps} ) {
|
||||
$_favApps = eval {
|
||||
from_json( $req->userData->{_favApps}, { allow_nonref => 1 } );
|
||||
};
|
||||
if ($@) {
|
||||
$self->logger->error("Corrupted session (_favApps): $@");
|
||||
return $self->p->sendError( $req, "Corrupted session", 500 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->logger->debug("No favorite Apps found for $user");
|
||||
$_favApps = [];
|
||||
}
|
||||
|
||||
# Append or remove favorite application
|
||||
my $nbrApps = @$_favApps;
|
||||
$self->logger->debug("$nbrApps favorite Apps found");
|
||||
if ( $nbrApps && $self->_isFavApp( $_favApps, $uri ) ) {
|
||||
$_favApps = $self->_removeFavApp( $_favApps, $uri );
|
||||
$self->p->updatePersistentSession( $req,
|
||||
{ _favApps => to_json($_favApps) } );
|
||||
$result = '{"result":0}';
|
||||
$self->userLogger->notice(
|
||||
"Favorite apps deletion of $uri succeeds for $user");
|
||||
}
|
||||
else {
|
||||
if ( $nbrApps < $self->conf->{favAppsMaxNumber} ) {
|
||||
$_favApps =
|
||||
$self->_appendFavApp( $_favApps, $uri, $id, $logo, $desc, $name );
|
||||
$self->p->updatePersistentSession( $req,
|
||||
{ _favApps => to_json($_favApps) } );
|
||||
$result = '{"result":1}';
|
||||
$self->userLogger->notice(
|
||||
"Favorite apps registration of $uri succeeds for $user");
|
||||
}
|
||||
else {
|
||||
$result = '{"error":1}';
|
||||
$self->userLogger->notice(
|
||||
"Max number of favorite apps reached for $user");
|
||||
}
|
||||
}
|
||||
return [
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/json',
|
||||
'Content-Length' => length($result),
|
||||
],
|
||||
[$result]
|
||||
];
|
||||
}
|
||||
|
||||
sub read {
|
||||
my ( $self, $req ) = @_;
|
||||
my $user = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
|
||||
# Read existing favorite Apps
|
||||
$self->logger->debug("Looking for favorite Apps...");
|
||||
my $_favApps;
|
||||
if ( $req->userData->{_favApps} ) {
|
||||
$_favApps = eval {
|
||||
from_json( $req->userData->{_favApps}, { allow_nonref => 1 } );
|
||||
};
|
||||
if ($@) {
|
||||
$self->logger->error("Corrupted session (_favApps): $@");
|
||||
return $self->p->sendError( $req, "Corrupted session", 500 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->logger->debug("No favorite Apps found");
|
||||
$_favApps = [];
|
||||
}
|
||||
|
||||
# Serialize data
|
||||
my $data = to_json( {
|
||||
result => 1,
|
||||
apps => $_favApps
|
||||
}
|
||||
);
|
||||
$self->logger->debug(
|
||||
scalar @$_favApps . " favorite Apps found for $user" );
|
||||
|
||||
return [
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/json',
|
||||
'Content-Length' => length($data),
|
||||
],
|
||||
[$data]
|
||||
];
|
||||
}
|
||||
|
||||
sub reset {
|
||||
my ( $self, $req ) = @_;
|
||||
my $user = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
$self->p->updatePersistentSession( $req, { _favApps => '' } );
|
||||
$self->userLogger->notice("$user favorite Apps. RESET");
|
||||
|
||||
return [
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/json',
|
||||
'Content-Length' => 12,
|
||||
],
|
||||
['{"result":1}']
|
||||
];
|
||||
}
|
||||
|
||||
sub _isFavApp {
|
||||
my ( $self, $_favApps, $uri ) = @_;
|
||||
my $test = 0;
|
||||
foreach (@$_favApps) {
|
||||
if ( $_->{appuri} eq $uri ) {
|
||||
$test = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
$self->logger->debug("App. already registered? $test");
|
||||
return $test;
|
||||
}
|
||||
|
||||
sub _appendFavApp {
|
||||
my ( $self, $_favApps, $uri, $id, $logo, $desc, $name ) = @_;
|
||||
push @$_favApps,
|
||||
{
|
||||
appuri => $uri,
|
||||
appid => $id,
|
||||
applogo => $logo,
|
||||
appdesc => $desc,
|
||||
appname => $name
|
||||
};
|
||||
$self->logger->debug("App. $uri appended");
|
||||
return $_favApps;
|
||||
}
|
||||
|
||||
sub _removeFavApp {
|
||||
my ( $self, $_favApps, $uri ) = @_;
|
||||
@$_favApps = grep { $_->{appuri} ne $uri } @$_favApps;
|
||||
$self->logger->debug("App. $uri removed");
|
||||
return $_favApps;
|
||||
}
|
||||
|
||||
1;
|
50
lemonldap-ng-portal/site/coffee/favapps.coffee
Normal file
50
lemonldap-ng-portal/site/coffee/favapps.coffee
Normal file
|
@ -0,0 +1,50 @@
|
|||
###
|
||||
LemonLDAP::NG Favorite Applications script
|
||||
###
|
||||
|
||||
# FavApps function (launched by "star" icon)
|
||||
FavApps = (star) ->
|
||||
$.ajax
|
||||
type: "POST"
|
||||
url: "#{portal}favapps"
|
||||
data:
|
||||
id: star.attr 'aid'
|
||||
uri: star.attr 'uri'
|
||||
name: star.attr 'name'
|
||||
logo: star.attr 'logo'
|
||||
desc: star.attr 'desc'
|
||||
dataType: 'json'
|
||||
success: (resp) ->
|
||||
if resp.error
|
||||
console.log 'Max number reached'
|
||||
switchStar star, 0
|
||||
else if resp.error == 0
|
||||
console.log 'Not authorized'
|
||||
switchStar star, 0
|
||||
else if resp.result
|
||||
console.log 'App. registered'
|
||||
switchStar star, 1
|
||||
else
|
||||
console.log 'App. unregistered'
|
||||
switchStar star, 0
|
||||
error: switchStar star, '0'
|
||||
|
||||
ResetFavApps = ->
|
||||
$.ajax
|
||||
type: "DELETE"
|
||||
url: "#{portal}favapps"
|
||||
success: (resp) ->
|
||||
if resp.result
|
||||
console.log 'Favorite Apps. reset'
|
||||
window.location.reload()
|
||||
else
|
||||
console.log 'Error'
|
||||
|
||||
switchStar = (star, status) ->
|
||||
star.attr('src', "#{window.staticPrefix}common/icons/star#{status}.png")
|
||||
#window.location.reload()
|
||||
|
||||
# Switch "star" ans Reset events
|
||||
$(document).ready ->
|
||||
$('body').on 'click', '.star', () -> FavApps $(this)
|
||||
$('#reset').on 'click', () -> ResetFavApps()
|
|
@ -17,7 +17,7 @@ displayError = (j, status, err) ->
|
|||
console.log 'Returned error', res
|
||||
setMsg res, 'warning'
|
||||
|
||||
token=''
|
||||
token = ''
|
||||
|
||||
getKey = (reset) ->
|
||||
setMsg 'yourTotpKey', 'warning'
|
||||
|
|
BIN
lemonldap-ng-portal/site/htdocs/static/common/icons/star0.png
Normal file
BIN
lemonldap-ng-portal/site/htdocs/static/common/icons/star0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
lemonldap-ng-portal/site/htdocs/static/common/icons/star1.png
Normal file
BIN
lemonldap-ng-portal/site/htdocs/static/common/icons/star1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
69
lemonldap-ng-portal/site/htdocs/static/common/js/favapps.js
Normal file
69
lemonldap-ng-portal/site/htdocs/static/common/js/favapps.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Generated by CoffeeScript 1.12.7
|
||||
|
||||
/*
|
||||
LemonLDAP::NG Favorite Applications script
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var FavApps, ResetFavApps, switchStar;
|
||||
|
||||
FavApps = function(star) {
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
url: portal + "favapps",
|
||||
data: {
|
||||
id: star.attr('aid'),
|
||||
uri: star.attr('uri'),
|
||||
name: star.attr('name'),
|
||||
logo: star.attr('logo'),
|
||||
desc: star.attr('desc')
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(resp) {
|
||||
if (resp.error) {
|
||||
console.log('Max number reached');
|
||||
return switchStar(star, 0);
|
||||
} else if (resp.error === 0) {
|
||||
console.log('Not authorized');
|
||||
return switchStar(star, 0);
|
||||
} else if (resp.result) {
|
||||
console.log('App. registered');
|
||||
return switchStar(star, 1);
|
||||
} else {
|
||||
console.log('App. unregistered');
|
||||
return switchStar(star, 0);
|
||||
}
|
||||
},
|
||||
error: switchStar(star, '0')
|
||||
});
|
||||
};
|
||||
|
||||
ResetFavApps = function() {
|
||||
return $.ajax({
|
||||
type: "DELETE",
|
||||
url: portal + "favapps",
|
||||
success: function(resp) {
|
||||
if (resp.result) {
|
||||
console.log('Favorite Apps. reset');
|
||||
return window.location.reload();
|
||||
} else {
|
||||
return console.log('Error');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
switchStar = function(star, status) {
|
||||
return star.attr('src', window.staticPrefix + "common/icons/star" + status + ".png");
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
$('body').on('click', '.star', function() {
|
||||
return FavApps($(this));
|
||||
});
|
||||
return $('#reset').on('click', function() {
|
||||
return ResetFavApps();
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
1
lemonldap-ng-portal/site/htdocs/static/common/js/favapps.min.js
vendored
Normal file
1
lemonldap-ng-portal/site/htdocs/static/common/js/favapps.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
(function(){var FavApps,ResetFavApps,switchStar;FavApps=function(star){return $.ajax({type:"POST",url:portal+"favapps",data:{id:star.attr("aid"),uri:star.attr("uri"),name:star.attr("name"),logo:star.attr("logo"),desc:star.attr("desc")},dataType:"json",success:function(resp){if(resp.error){console.log("Max number reached");return switchStar(star,0)}else if(resp.error===0){console.log("Not authorized");return switchStar(star,0)}else if(resp.result){console.log("App. registered");return switchStar(star,1)}else{console.log("App. unregistered");return switchStar(star,0)}},error:switchStar(star,"0")})};ResetFavApps=function(){return $.ajax({type:"DELETE",url:portal+"favapps",success:function(resp){if(resp.result){console.log("Favorite Apps. reset");return window.location.reload()}else{return console.log("Error")}}})};switchStar=function(star,status){return star.attr("src",window.staticPrefix+"common/icons/star"+status+".png")};$(document).ready(function(){$("body").on("click",".star",function(){return FavApps($(this))});return $("#reset").on("click",function(){return ResetFavApps()})})}).call(this);
|
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.8
|
||||
// Generated by CoffeeScript 1.12.7
|
||||
|
||||
/*
|
||||
LemonLDAP::NG TOTP registration script
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"يرجى استخدام يوبي كي الخاص بك",
|
||||
"errorMsg":"رسالة خاطئة",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"الاسم الاول",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"إزالة الجلسات الأخرى",
|
||||
"resendConfirmMail":"هل تريد إعادة إرسال رسالة التأكيد؟",
|
||||
"resentConfirm":"هل تريد إعادة إرسال رسالة التأكيد؟",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"إعادة تعيين كلمة المرور الخاصة بي",
|
||||
"rightsReloadNeedsLogout":" إعادة تحميل الحقوق تحتاج إلى تسجيل الخروج وتسجيل الدخول مرة أخرى",
|
||||
"scope":"نطاق",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Gebe den TOTP Code ein",
|
||||
"enterYubikey":"Benutze bitte deinen Yubikey",
|
||||
"errorMsg":"Fehlermeldung",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fülle das Formular aus",
|
||||
"firstName":"Vorname",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Andere Sitzungen löschen",
|
||||
"resendConfirmMail":"Bestätigungsmail erneuert senden ?",
|
||||
"resentConfirm":"Möchtest du, dass die Bestätigungsmail erneut gesendet wird ?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Mein Passwort zurücksetzen",
|
||||
"rightsReloadNeedsLogout":"Zum Neuladen der Rechte musst du dich ab- und wieder anmelden",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Please use your Yubikey",
|
||||
"errorMsg":"Error Message",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"First name",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Remove other sessions",
|
||||
"resendConfirmMail":"Resend confirmation mail?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Reset my password",
|
||||
"rightsReloadNeedsLogout": "Rights reloads need to logout and login again",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Please use your Yubikey",
|
||||
"errorMsg":"Error Message",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"First name",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Remove other sessions",
|
||||
"resendConfirmMail":"Resend confirmation mail?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Reset my password",
|
||||
"rightsReloadNeedsLogout":"Rights reloads need to logout and login again",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Please use your Yubikey",
|
||||
"errorMsg":"Virhe viesti",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"Etunimi",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Remove other sessions",
|
||||
"resendConfirmMail":"Uudelleen lähetä vahvistus sähköposti?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Palauta salasanani?",
|
||||
"rightsReloadNeedsLogout":"Rights reloads need to logout and login again",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Entrez le code TOTP",
|
||||
"enterYubikey":"Utilisez votre Yubikey",
|
||||
"errorMsg":"Message d'erreur",
|
||||
"yourFavApps":"Applications favorites",
|
||||
"fillTheForm":"Remplissez le formulaire",
|
||||
"forbidden":"Accès INTERDIT",
|
||||
"firstName":"Prénom",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Fermer les autres sessions",
|
||||
"resendConfirmMail":"Renvoyer le mail de confirmation ?",
|
||||
"resentConfirm":"Voulez-vous que le message de confirmation soit renvoyé ?",
|
||||
"resetFavApps":"Réinitialiser mes applications favorites",
|
||||
"resetPwd":"Réinitialiser mon mot de passe",
|
||||
"rightsReloadNeedsLogout": "Le rechargement des droits nécessite une déconnexion",
|
||||
"scope": "Informations",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Inserisci il codice TOTP",
|
||||
"enterYubikey":"Utilizza il tuo Yubikey",
|
||||
"errorMsg":"Messaggio di errore",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Compila il modulo",
|
||||
"firstName":"Nome",
|
||||
"forbidden":"Accesso VIETATO",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Rimuovere altre sessioni",
|
||||
"resendConfirmMail":"Inviare nuovamente mail di conferma?",
|
||||
"resentConfirm":"Vuoi inviare di nuovo la mail di conferma?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Reimpostare la password",
|
||||
"rightsReloadNeedsLogout":"Le ricariche dei diritti necessitano di disconnettersi e di riconnettersi",
|
||||
"scope":"Ambito",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Please use your Yubikey",
|
||||
"errorMsg":"Error Message",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"First name",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Remove other sessions",
|
||||
"resendConfirmMail":"Resend confirmation mail?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Reset my password",
|
||||
"rightsReloadNeedsLogout":"Rights reloads need to logout and login again",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Please use your Yubikey",
|
||||
"errorMsg":"Error Message",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"First name",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Remove other sessions",
|
||||
"resendConfirmMail":"Resend confirmation mail?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Reset my password",
|
||||
"rightsReloadNeedsLogout":"Rights reloads need to logout and login again",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Please use your Yubikey",
|
||||
"errorMsg":"Error Message",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"First name",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Remove other sessions",
|
||||
"resendConfirmMail":"Resend confirmation mail?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Reset my password",
|
||||
"rightsReloadNeedsLogout":"Rights reloads need to logout and login again",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"Vui lòng sử dụng Yubikey của bạn",
|
||||
"errorMsg":"Thông báo lỗi",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"Tên",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"Xóa các phiên khác",
|
||||
"resendConfirmMail":"Gửi lại thư xác nhận?",
|
||||
"resentConfirm":"Bạn có muốn gửi lại thư xác nhận không?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"Đặt lại mật khẩu của tôi",
|
||||
"rightsReloadNeedsLogout":"Tải lại quyền cần đăng xuất và đăng nhập lại",
|
||||
"scope":"Phạm vi",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"enterTotpCode":"Enter TOTP code",
|
||||
"enterYubikey":"请使用您的Yubikey",
|
||||
"errorMsg":"错误消息",
|
||||
"yourFavApps":"Favorite applications",
|
||||
"fillTheForm":"Fill the form",
|
||||
"firstName":"名",
|
||||
"forbidden":"Access FORBIDDEN",
|
||||
|
@ -199,6 +200,7 @@
|
|||
"removeOtherSessions":"移除其他会话",
|
||||
"resendConfirmMail":"重新发送确认邮件?",
|
||||
"resentConfirm":"您想确认邮件被重新发送吗?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetPwd":"重置我的密码",
|
||||
"rightsReloadNeedsLogout":"重新加载权限需要登出并且再次登录",
|
||||
"scope":"Scope",
|
||||
|
|
|
@ -42,14 +42,17 @@
|
|||
<!-- //if:usedebianlibs
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX"><TMPL_VAR NAME="SKIN">/js/skin.min.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/portal.min.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/favapps.min.js"></script>
|
||||
<script type="text/javascript" src="/javascript/bootstrap4/js/bootstrap.min.js"></script>
|
||||
//elsif:jsminified
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX"><TMPL_VAR NAME="SKIN">/js/skin.min.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/portal.min.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/favapps.min.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
//else -->
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX"><TMPL_VAR NAME="SKIN">/js/skin.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/portal.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/favapps.js"></script>
|
||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/bootstrap/dist/js/bootstrap.js"></script>
|
||||
<!-- //endif -->
|
||||
<TMPL_VAR NAME="CUSTOM_SCRIPT">
|
||||
|
|
|
@ -20,7 +20,12 @@
|
|||
<!-- Tabs list -->
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<TMPL_LOOP NAME="DISPLAY_MODULES">
|
||||
|
||||
<TMPL_IF NAME="FavApps">
|
||||
<li class="nav-item"><a class="nav-link" href="#favApps"><span>
|
||||
<img src="<TMPL_VAR NAME="STATIC_PREFIX">common/icons/star1.png" width="16" height="16" alt="yourFavApps" />
|
||||
<span trspan="yourFavApps">Your favorite applications</span>
|
||||
</span></a></li>
|
||||
</TMPL_IF>
|
||||
<TMPL_IF NAME="Appslist">
|
||||
<li class="nav-item"><a class="nav-link" href="#appslist"><span>
|
||||
<img src="<TMPL_VAR NAME="STATIC_PREFIX">common/icons/application_cascade.png" width="16" height="16" alt="appslist" />
|
||||
|
@ -42,7 +47,7 @@
|
|||
<TMPL_IF NAME="OidcConsents">
|
||||
<li class="nav-item"><a class="nav-link" href="#oidcConsents"><span>
|
||||
<img src="<TMPL_VAR NAME="STATIC_PREFIX">common/icons/oidc.png" width="16" height="16" alt="login history" />
|
||||
<span trspan="oidcConsents">OIDC Consent</span>
|
||||
<span trspan="oidcConsents">OIDC Consents</span>
|
||||
</span></a></li>
|
||||
</TMPL_IF>
|
||||
<TMPL_IF NAME="Logout">
|
||||
|
@ -82,6 +87,68 @@
|
|||
|
||||
<!-- Tabs content -->
|
||||
<TMPL_LOOP NAME="DISPLAY_MODULES">
|
||||
<TMPL_IF NAME="FavApps">
|
||||
<div id="favApps">
|
||||
<div class="category cat-level-1 card border-secondary">
|
||||
<div class="card-header text-white bg-secondary">
|
||||
<h4 class="catname card-title" trspan="yourFavApps">Your favorite applications</h4>
|
||||
</div>
|
||||
<div id="favApps">
|
||||
<div class="card-body">
|
||||
<!-- Applications -->
|
||||
<div class="row">
|
||||
<TMPL_LOOP NAME="FAVAPPS_LOOP">
|
||||
|
||||
<!-- Application -->
|
||||
<div class="col-md-4">
|
||||
<div class="application <TMPL_VAR NAME="appid"> card">
|
||||
<a href="<TMPL_VAR NAME="appuri">" title="<TMPL_VAR NAME="appname">" >
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<!-- Logo (optional) -->
|
||||
<TMPL_IF NAME="applogo">
|
||||
<div class="col-3">
|
||||
<img src="<TMPL_VAR NAME="STATIC_PREFIX">common/apps/<TMPL_VAR NAME="applogo">"
|
||||
class="applogo <TMPL_VAR NAME="appid"> img-fluid"
|
||||
alt="<TMPL_VAR NAME="appname">" />
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<TMPL_ELSE>
|
||||
<div class="col-12">
|
||||
</TMPL_IF>
|
||||
|
||||
<!-- Name and link (mandatory) -->
|
||||
<h5 class="appname <TMPL_VAR NAME="appid"> card-title">
|
||||
<TMPL_VAR NAME="appname">
|
||||
</h5>
|
||||
|
||||
<!-- Description (optional) -->
|
||||
<TMPL_IF NAME="appdesc">
|
||||
<p class="appdesc <TMPL_VAR NAME="appid"> card-subtitle mb-2 text-muted">
|
||||
<TMPL_VAR NAME="appdesc">
|
||||
</p>
|
||||
</TMPL_IF>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End of applications loop -->
|
||||
</TMPL_LOOP>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span id="reset" class="btn btn-danger" role="button">
|
||||
<span class="fa fa-trash-o"></span>
|
||||
<span trspan="resetFavApps">Reset my favorite Apps.</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="Appslist">
|
||||
<div id="appslist">
|
||||
|
@ -107,7 +174,19 @@
|
|||
|
||||
<!-- Application -->
|
||||
<div class="col-md-4">
|
||||
<TMPL_IF NAME="STARS">
|
||||
<div>
|
||||
<img class="star"
|
||||
aid="<TMPL_VAR NAME="appid">"
|
||||
uri="<TMPL_VAR NAME="appuri">"
|
||||
name="<TMPL_VAR NAME="appname">"
|
||||
logo="<TMPL_VAR NAME="applogo">"
|
||||
desc="<TMPL_VAR NAME="appdesc">"
|
||||
src="<TMPL_VAR NAME="STATIC_PREFIX">common/icons/star<TMPL_VAR NAME="appisfav">.png"/>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
<div class="application <TMPL_VAR NAME="appid"> card">
|
||||
|
||||
<a href="<TMPL_VAR NAME="appuri">" title="<TMPL_VAR NAME="appname">" >
|
||||
|
||||
<div class="card-body">
|
||||
|
@ -126,6 +205,7 @@
|
|||
|
||||
<!-- Name and link (mandatory) -->
|
||||
<h5 class="appname <TMPL_VAR NAME="appid"> card-title">
|
||||
|
||||
<TMPL_VAR NAME="appname">
|
||||
</h5>
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ sub op {
|
|||
oidcRPMetaDataOptionsDisplayName => "RP",
|
||||
oidcRPMetaDataOptionsIDTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsClientID => "rpid",
|
||||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsIDTokenSignAlg => "RS512",
|
||||
oidcRPMetaDataOptionsBypassConsent => 0,
|
||||
oidcRPMetaDataOptionsPublic => 1,
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
|
|
200
lemonldap-ng-portal/t/69-FavApps.t
Normal file
200
lemonldap-ng-portal/t/69-FavApps.t
Normal file
|
@ -0,0 +1,200 @@
|
|||
use Test::More;
|
||||
use strict;
|
||||
use IO::String;
|
||||
|
||||
BEGIN {
|
||||
require 't/test-lib.pm';
|
||||
}
|
||||
|
||||
my $res;
|
||||
|
||||
my $client = LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
brutForceProtection => 0,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
checkUser => 0,
|
||||
portalDisplayFavApps => 1,
|
||||
portalDisplayOidcConsents => 1,
|
||||
portalDisplayLoginHistory => 1,
|
||||
portalDisplayAppslist => 1,
|
||||
portalDisplayLogout => 1,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
## Try to authenticate
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new('user=dwho&password=dwho'),
|
||||
length => 23,
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
count(1);
|
||||
|
||||
my $id = expectCookie($res);
|
||||
expectRedirection( $res, 'http://auth.example.com/' );
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Get Menu'
|
||||
);
|
||||
count(1);
|
||||
|
||||
# Parse Menu
|
||||
my @menu =
|
||||
map m%<li class="nav-item"><a class="nav-link" href="#(.+)?"><span>%g,
|
||||
$res->[2]->[0];
|
||||
ok( scalar @menu == 5, 'Menu with five links found' )
|
||||
or print STDERR Dumper($res);
|
||||
ok( $menu[0] eq 'appslist', 'appslist link found' )
|
||||
or print STDERR Dumper( \@menu );
|
||||
ok( $menu[1] eq 'password', 'password link found' )
|
||||
or print STDERR Dumper( \@menu );
|
||||
ok( $menu[2] eq 'loginHistory', 'loginHistory link found' )
|
||||
or print STDERR Dumper( \@menu );
|
||||
ok( $menu[3] eq 'oidcConsents', 'oidcConsents link found' )
|
||||
or print STDERR Dumper( \@menu );
|
||||
ok( $menu[4] eq 'logout', 'logout link found' )
|
||||
or print STDERR Dumper( \@menu );
|
||||
count(6);
|
||||
|
||||
my @stars =
|
||||
map m%src="/static/common/icons/star0\.png"/>%g,
|
||||
$res->[2]->[0];
|
||||
ok( scalar @stars == 3, 'Three silver stars found' )
|
||||
or print STDERR Dumper($res);
|
||||
count(1);
|
||||
|
||||
## Try to register a favorite app
|
||||
my $query =
|
||||
'id=0002-app&uri=http%3A%2F%2Ftest1.example.com%2F&name=Application+Test+1&logo=demo.png&desc=A+simple+application+displaying+authenticated+user';
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/favapps',
|
||||
IO::String->new($query),
|
||||
cookie => "lemonldap=$id",
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Register Test1 FavApp query'
|
||||
);
|
||||
$query =
|
||||
'id=0006-app&uri=http%3A%2F%2Fmanager.example.com%2Fnotifications.html&name=Notifications+explorer&logo=database.png&desc=Explore+WebSSO+notifications
|
||||
';
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/favapps',
|
||||
IO::String->new($query),
|
||||
cookie => "lemonldap=$id",
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Register Notifications FavApp query'
|
||||
);
|
||||
count(2);
|
||||
|
||||
# Parse Page
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Get Menu'
|
||||
);
|
||||
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/logo_llng_old.png"%,
|
||||
'Found custom Main Logo' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
@stars =
|
||||
map m%src="/static/common/icons/star1\.png"/>%g,
|
||||
$res->[2]->[0];
|
||||
ok( scalar @stars == 2, 'Two gold stars found' )
|
||||
or print STDERR Dumper($res);
|
||||
@stars =
|
||||
map m%src="/static/common/icons/star0\.png"/>%g,
|
||||
$res->[2]->[0];
|
||||
ok( scalar @stars == 1, 'One silver star found' )
|
||||
or print STDERR Dumper($res);
|
||||
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<span trspan="resetFavApps">Reset my favorite Apps\.</span>%,
|
||||
'Found resetFavApps button'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(5);
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/favapps',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'application/json',
|
||||
),
|
||||
'Get FavApps'
|
||||
);
|
||||
eval { $res = JSON::from_json( $res->[2]->[0] ) };
|
||||
ok( not($@), 'Content is JSON' )
|
||||
or explain( $res->[2]->[0], 'JSON content' );
|
||||
ok( $res->{result} == 1, 'FavApps received' );
|
||||
ok(
|
||||
$res->{apps}->[0]->{appuri} =~ m%http://test1.example.com/%,
|
||||
'Found favorite Apps -> http://test1.example.com'
|
||||
) or explain( $res->{apps}, "test1 FavApps NOT registered" );
|
||||
ok(
|
||||
$res->{apps}->[0]->{appdesc} =~
|
||||
m%A simple application displaying authenticated user%,
|
||||
'Found favorite Apps description'
|
||||
) or explain( $res->{apps}, "description NOT registered" );
|
||||
ok( $res->{apps}->[0]->{applogo} =~ m%demo\.png%, 'Found favorite Apps logo' )
|
||||
or explain( $res->{apps}, "logo NOT registered" );
|
||||
ok( $res->{apps}->[0]->{appname} =~ m%Application Test 1%,
|
||||
'Found favorite Apps name' )
|
||||
or explain( $res->{apps}, "name NOT registered" );
|
||||
ok( $res->{apps}->[0]->{appid} =~ m%0002-app%, 'Found favorite Apps id' )
|
||||
or explain( $res->{apps}, "id NOT registered" );
|
||||
ok(
|
||||
$res->{apps}->[1]->{appuri} =~
|
||||
m%http://manager.example.com/notifications.html%,
|
||||
'Found favorite Apps -> http://manager.example.com/notifications.html'
|
||||
) or explain( $res->{apps}, "notifications FavApps NOT registered" );
|
||||
count(9);
|
||||
|
||||
ok(
|
||||
$res = $client->_delete(
|
||||
'/favapps',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'application/json',
|
||||
),
|
||||
'Delete FavApps'
|
||||
);
|
||||
count(1);
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/favapps',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'application/json',
|
||||
),
|
||||
'Get FavApps'
|
||||
);
|
||||
eval { $res = JSON::from_json( $res->[2]->[0] ) };
|
||||
ok( not($@), 'Content is JSON' )
|
||||
or explain( $res->[2]->[0], 'JSON content' );
|
||||
ok( $res->{result} == 1, 'FavApps received' );
|
||||
ok( scalar @{ $res->{apps} } == 0, 'NO favorite Apps found' )
|
||||
or explain( $res->{apps}, "FavApps NOT deleted" );
|
||||
count(4);
|
||||
|
||||
$client->logout($id);
|
||||
clean_sessions();
|
||||
|
||||
done_testing( count() );
|
|
@ -1,4 +1,44 @@
|
|||
{
|
||||
"applicationList" : {
|
||||
"1sample" : {
|
||||
"catname" : "Sample applications",
|
||||
"test1" : {
|
||||
"options" : {
|
||||
"description" : "A simple application displaying authenticated user",
|
||||
"display" : "auto",
|
||||
"logo" : "demo.png",
|
||||
"name" : "Application Test 1",
|
||||
"uri" : "http://test1.example.com/"
|
||||
},
|
||||
"type" : "application"
|
||||
},
|
||||
"test2" : {
|
||||
"options" : {
|
||||
"description" : "The same simple application displaying authenticated user",
|
||||
"display" : "auto",
|
||||
"logo" : "thumbnail.png",
|
||||
"name" : "Application Test 2",
|
||||
"uri" : "http://test2.example.com/"
|
||||
},
|
||||
"type" : "application"
|
||||
},
|
||||
"type" : "category"
|
||||
},
|
||||
"2administration" : {
|
||||
"catname" : "Administration",
|
||||
"notifications" : {
|
||||
"options" : {
|
||||
"description" : "Explore WebSSO notifications",
|
||||
"display" : "auto",
|
||||
"logo" : "database.png",
|
||||
"name" : "Notifications explorer",
|
||||
"uri" : "http://manager.example.com/notifications.html"
|
||||
},
|
||||
"type" : "application"
|
||||
},
|
||||
"type" : "category"
|
||||
}
|
||||
},
|
||||
"authentication": "Demo",
|
||||
"cfgAuthor": "The LemonLDAP::NG team",
|
||||
"cfgAuthorIP": "127.0.0.1",
|
||||
|
|
Loading…
Reference in New Issue
Block a user