Merge branch 'v2.0'
TODO: Fix OIDC
This commit is contained in:
commit
947dd9a438
|
@ -8,6 +8,18 @@
|
||||||
paths:
|
paths:
|
||||||
- result/*
|
- result/*
|
||||||
|
|
||||||
|
|
||||||
|
.build_job_centos:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- yum -y install epel-release
|
||||||
|
- make rpm-dist
|
||||||
|
- ci-build-pkg
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 day
|
||||||
|
paths:
|
||||||
|
- result/*
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- sign
|
- sign
|
||||||
|
@ -46,6 +58,10 @@ build_bionic:
|
||||||
image: buildpkg/ubuntu:bionic
|
image: buildpkg/ubuntu:bionic
|
||||||
<<: *job_build
|
<<: *job_build
|
||||||
|
|
||||||
|
build_centos_7:
|
||||||
|
image: buildpkg/centos:7
|
||||||
|
extends: .build_job_centos
|
||||||
|
|
||||||
sign:
|
sign:
|
||||||
image: buildpkg/debian:stretch
|
image: buildpkg/debian:stretch
|
||||||
stage: sign
|
stage: sign
|
||||||
|
@ -60,6 +76,7 @@ sign:
|
||||||
- build_buster
|
- build_buster
|
||||||
- build_disco
|
- build_disco
|
||||||
- build_bionic
|
- build_bionic
|
||||||
|
- build_centos_7
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 1 day
|
expire_in: 1 day
|
||||||
paths:
|
paths:
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -129,8 +129,8 @@ E2E_TESTS='portal/*.js'
|
||||||
|
|
||||||
# LDAP backend test
|
# LDAP backend test
|
||||||
LLNGTESTLDAP_SLAPD_BIN=/usr/sbin/slapd
|
LLNGTESTLDAP_SLAPD_BIN=/usr/sbin/slapd
|
||||||
LLNGTESTLDAP_SLAPADD_BIN=/usr/sbin/slapdadd
|
LLNGTESTLDAP_SLAPADD_BIN=/usr/sbin/slapadd
|
||||||
LLNGTESTLDAP_SCHEMA_DIR=/etc/slapd/schema
|
LLNGTESTLDAP_SCHEMA_DIR=/etc/ldap/schema
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
SRCCOMMONDIR=lemonldap-ng-common
|
SRCCOMMONDIR=lemonldap-ng-common
|
||||||
|
@ -623,6 +623,7 @@ install_bin: install_conf_dir
|
||||||
${SRCPORTALDIR}/site/cron/purgeCentralCache \
|
${SRCPORTALDIR}/site/cron/purgeCentralCache \
|
||||||
${SRCPORTALDIR}/scripts/llngDeleteSession \
|
${SRCPORTALDIR}/scripts/llngDeleteSession \
|
||||||
${SRCCOMMONDIR}/scripts/convertConfig \
|
${SRCCOMMONDIR}/scripts/convertConfig \
|
||||||
|
${SRCCOMMONDIR}/scripts/convertSessions \
|
||||||
${SRCCOMMONDIR}/scripts/lmMigrateConfFiles2ini \
|
${SRCCOMMONDIR}/scripts/lmMigrateConfFiles2ini \
|
||||||
${SRCCOMMONDIR}/scripts/rotateOidcKeys \
|
${SRCCOMMONDIR}/scripts/rotateOidcKeys \
|
||||||
${SRCMANAGERDIR}/scripts/lmConfigEditor \
|
${SRCMANAGERDIR}/scripts/lmConfigEditor \
|
||||||
|
|
|
@ -18,6 +18,16 @@
|
||||||
auth_request_set $headervalue9 $upstream_http_headervalue9;
|
auth_request_set $headervalue9 $upstream_http_headervalue9;
|
||||||
auth_request_set $headername10 $upstream_http_headername10;
|
auth_request_set $headername10 $upstream_http_headername10;
|
||||||
auth_request_set $headervalue10 $upstream_http_headervalue10;
|
auth_request_set $headervalue10 $upstream_http_headervalue10;
|
||||||
|
auth_request_set $headername11 $upstream_http_headername11;
|
||||||
|
auth_request_set $headervalue11 $upstream_http_headervalue11;
|
||||||
|
auth_request_set $headername12 $upstream_http_headername12;
|
||||||
|
auth_request_set $headervalue12 $upstream_http_headervalue12;
|
||||||
|
auth_request_set $headername13 $upstream_http_headername13;
|
||||||
|
auth_request_set $headervalue13 $upstream_http_headervalue13;
|
||||||
|
auth_request_set $headername14 $upstream_http_headername14;
|
||||||
|
auth_request_set $headervalue14 $upstream_http_headervalue14;
|
||||||
|
auth_request_set $headername15 $upstream_http_headername15;
|
||||||
|
auth_request_set $headervalue15 $upstream_http_headervalue15;
|
||||||
auth_request_set $lmcookie $upstream_http_cookie;
|
auth_request_set $lmcookie $upstream_http_cookie;
|
||||||
access_by_lua '
|
access_by_lua '
|
||||||
i = 1
|
i = 1
|
||||||
|
|
2
debian/liblemonldap-ng-common-perl.install
vendored
2
debian/liblemonldap-ng-common-perl.install
vendored
|
@ -1,12 +1,14 @@
|
||||||
/etc/lemonldap-ng/lemonldap-ng.ini
|
/etc/lemonldap-ng/lemonldap-ng.ini
|
||||||
/etc/lemonldap-ng/for_etc_hosts
|
/etc/lemonldap-ng/for_etc_hosts
|
||||||
/usr/share/man/man1/convertConfig.1p
|
/usr/share/man/man1/convertConfig.1p
|
||||||
|
/usr/share/man/man1/convertSessions.1p
|
||||||
/usr/share/man/man1/lemonldap-ng-cli.1p
|
/usr/share/man/man1/lemonldap-ng-cli.1p
|
||||||
/usr/share/man/man3/Lemonldap::NG::Common*
|
/usr/share/man/man3/Lemonldap::NG::Common*
|
||||||
/usr/share/perl5/auto/Lemonldap/NG/Common
|
/usr/share/perl5/auto/Lemonldap/NG/Common
|
||||||
/usr/share/perl5/Lemonldap/NG/Common*
|
/usr/share/perl5/Lemonldap/NG/Common*
|
||||||
/usr/share/lemonldap-ng/ressources
|
/usr/share/lemonldap-ng/ressources
|
||||||
/usr/share/lemonldap-ng/bin/convertConfig
|
/usr/share/lemonldap-ng/bin/convertConfig
|
||||||
|
/usr/share/lemonldap-ng/bin/convertSessions
|
||||||
/usr/share/lemonldap-ng/bin/importMetadata
|
/usr/share/lemonldap-ng/bin/importMetadata
|
||||||
/usr/share/lemonldap-ng/bin/lmMigrateConfFiles2ini
|
/usr/share/lemonldap-ng/bin/lmMigrateConfFiles2ini
|
||||||
/usr/share/lemonldap-ng/bin/rotateOidcKeys
|
/usr/share/lemonldap-ng/bin/rotateOidcKeys
|
||||||
|
|
|
@ -66,7 +66,7 @@ describe('00 Lemonldap::NG', function() {
|
||||||
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('ohwd');
|
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('ohwd');
|
||||||
browser.driver.findElement(by.xpath("//input[@name='checkLogins']")).click();
|
browser.driver.findElement(by.xpath("//input[@name='checkLogins']")).click();
|
||||||
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
|
||||||
expect(browser.driver.findElement(by.css('[trmsg="5"]')).getText()).toEqual('Mot de passe ou identifiant incorrect');
|
expect(browser.driver.findElement(by.css('[trmsg="5"]')).getText()).toEqual('Identifiant ou mot de passe incorrect');
|
||||||
browser.driver.findElement(by.css('[trspan="goToPortal"]')).click();
|
browser.driver.findElement(by.css('[trspan="goToPortal"]')).click();
|
||||||
|
|
||||||
// Login attempt
|
// Login attempt
|
||||||
|
|
|
@ -129,7 +129,7 @@
|
||||||
.\" ========================================================================
|
.\" ========================================================================
|
||||||
.\"
|
.\"
|
||||||
.IX Title "llng-fastcgi-server 8"
|
.IX Title "llng-fastcgi-server 8"
|
||||||
.TH llng-fastcgi-server 8 "2019-10-30" "perl v5.26.1" "User Contributed Perl Documentation"
|
.TH llng-fastcgi-server 8 "2019-11-08" "perl v5.26.1" "User Contributed Perl Documentation"
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||||
.\" way too many mistakes in technical documents.
|
.\" way too many mistakes in technical documents.
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
|
|
|
@ -71,6 +71,7 @@ META.json
|
||||||
META.yml
|
META.yml
|
||||||
README
|
README
|
||||||
scripts/convertConfig
|
scripts/convertConfig
|
||||||
|
scripts/convertSessions
|
||||||
scripts/importMetadata
|
scripts/importMetadata
|
||||||
scripts/lemonldap-ng-cli
|
scripts/lemonldap-ng-cli
|
||||||
scripts/lmMigrateConfFiles2ini
|
scripts/lmMigrateConfFiles2ini
|
||||||
|
|
|
@ -90,6 +90,7 @@ WriteMakefile(
|
||||||
},
|
},
|
||||||
MAN1PODS => {
|
MAN1PODS => {
|
||||||
'scripts/convertConfig' => 'blib/man1/convertConfig.1p',
|
'scripts/convertConfig' => 'blib/man1/convertConfig.1p',
|
||||||
|
'scripts/convertSessions' => 'blib/man1/convertSessions.1p',
|
||||||
'scripts/lemonldap-ng-cli' => 'blib/man1/lemonldap-ng-cli.1p',
|
'scripts/lemonldap-ng-cli' => 'blib/man1/lemonldap-ng-cli.1p',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -85,11 +85,12 @@ logLevel = warn
|
||||||
|
|
||||||
; CONFIGURATION CHECK
|
; CONFIGURATION CHECK
|
||||||
;
|
;
|
||||||
; By default, LLNG verify configuration at server start. If you use "reload"
|
; LLNG verify configuration at server start. If you use "reload" mechanism,
|
||||||
; mechanism local cache will be updated. configuration is checked locally every
|
; local cache will be updated. Configuration is checked locally every
|
||||||
; 10 minutes by each LLNG component. You can change this value using
|
; 10 minutes by each LLNG component. You can change this value using
|
||||||
; `checkTime` (time in seconds):
|
; `checkTime` (time in seconds).
|
||||||
;checkTime = 600
|
; To increase performances, you should comment this parameter and rely on cache.
|
||||||
|
checkTime = 1
|
||||||
|
|
||||||
[configuration]
|
[configuration]
|
||||||
|
|
||||||
|
|
|
@ -219,18 +219,24 @@ sub _dbiGKFAS {
|
||||||
$sth->execute;
|
$sth->execute;
|
||||||
my %res;
|
my %res;
|
||||||
while ( my @row = $sth->fetchrow_array ) {
|
while ( my @row = $sth->fetchrow_array ) {
|
||||||
if ( ref($data) eq 'CODE' ) {
|
eval {
|
||||||
my $tmp =
|
if ( ref($data) eq 'CODE' ) {
|
||||||
&$data( $args->{unserialize}->( $row[1], $next ), $row[0] );
|
my $tmp =
|
||||||
$res{ $row[0] } = $tmp if ( defined($tmp) );
|
&$data( $args->{unserialize}->( $row[1], $next ), $row[0] );
|
||||||
}
|
$res{ $row[0] } = $tmp if ( defined($tmp) );
|
||||||
elsif ($data) {
|
}
|
||||||
$data = [$data] unless ( ref($data) );
|
elsif ($data) {
|
||||||
my $tmp = $args->{unserialize}->( $row[1], $next );
|
$data = [$data] unless ( ref($data) );
|
||||||
$res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data);
|
my $tmp = $args->{unserialize}->( $row[1], $next );
|
||||||
}
|
$res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data);
|
||||||
else {
|
}
|
||||||
$res{ $row[0] } = $args->{unserialize}->( $row[1], $next );
|
else {
|
||||||
|
$res{ $row[0] } = $args->{unserialize}->( $row[1], $next );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
print STDERR "Error in session $row[0]\n";
|
||||||
|
delete $res{ $row[0] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return \%res;
|
return \%res;
|
||||||
|
@ -249,26 +255,32 @@ sub _FileGKFAS {
|
||||||
my %res;
|
my %res;
|
||||||
for my $f (@t) {
|
for my $f (@t) {
|
||||||
open F, '<', "$args->{Directory}/$f";
|
open F, '<', "$args->{Directory}/$f";
|
||||||
my $row = join '', <F>;
|
eval {
|
||||||
if ( ref($data) eq 'CODE' ) {
|
my $row = join '', <F>;
|
||||||
eval { $res{$f} = &$data( $args->{unserialize}->($row), $f ); };
|
if ( ref($data) eq 'CODE' ) {
|
||||||
if ($@) {
|
eval { $res{$f} = &$data( $args->{unserialize}->($row), $f ); };
|
||||||
$res{$f} = &$data( undef, $f );
|
if ($@) {
|
||||||
|
$res{$f} = &$data( undef, $f );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
elsif ($data) {
|
||||||
elsif ($data) {
|
$data = [$data] unless ( ref($data) );
|
||||||
$data = [$data] unless ( ref($data) );
|
my $tmp;
|
||||||
my $tmp;
|
eval { $tmp = $args->{unserialize}->($row); };
|
||||||
eval { $tmp = $args->{unserialize}->($row); };
|
if ($@) {
|
||||||
if ($@) {
|
$res{$f}->{$_} = undef foreach (@$data);
|
||||||
$res{$f}->{$_} = undef foreach (@$data);
|
}
|
||||||
|
else {
|
||||||
|
$res{$f}->{$_} = $tmp->{$_} foreach (@$data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$res{$f}->{$_} = $tmp->{$_} foreach (@$data);
|
eval { $res{$f} = $args->{unserialize}->($row); };
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
else {
|
if ($@) {
|
||||||
eval { $res{$f} = $args->{unserialize}->($row); };
|
print STDERR "Error in session $f\n";
|
||||||
|
delete $res{$f};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return \%res;
|
return \%res;
|
||||||
|
@ -318,17 +330,23 @@ sub _DBFileGKFAS {
|
||||||
|
|
||||||
my %res;
|
my %res;
|
||||||
foreach my $k ( keys %{ $class->{dbm} } ) {
|
foreach my $k ( keys %{ $class->{dbm} } ) {
|
||||||
if ( ref($data) eq 'CODE' ) {
|
eval {
|
||||||
$res{$k} =
|
if ( ref($data) eq 'CODE' ) {
|
||||||
&$data( $args->{unserialize}->( $class->{dbm}->{$k} ), $k );
|
$res{$k} =
|
||||||
}
|
&$data( $args->{unserialize}->( $class->{dbm}->{$k} ), $k );
|
||||||
elsif ($data) {
|
}
|
||||||
$data = [$data] unless ( ref($data) );
|
elsif ($data) {
|
||||||
my $tmp = $args->{unserialize}->( $class->{dbm}->{$k} );
|
$data = [$data] unless ( ref($data) );
|
||||||
$res{$k}->{$_} = $tmp->{$_} foreach (@$data);
|
my $tmp = $args->{unserialize}->( $class->{dbm}->{$k} );
|
||||||
}
|
$res{$k}->{$_} = $tmp->{$_} foreach (@$data);
|
||||||
else {
|
}
|
||||||
$res{$k} = $args->{unserialize}->( $class->{dbm}->{$k} );
|
else {
|
||||||
|
$res{$k} = $args->{unserialize}->( $class->{dbm}->{$k} );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
print STDERR "Error in session $k\n";
|
||||||
|
delete $res{$k};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return \%res;
|
return \%res;
|
||||||
|
|
|
@ -50,10 +50,12 @@ sub compactConf {
|
||||||
|
|
||||||
# Disabled for now:
|
# Disabled for now:
|
||||||
|
|
||||||
# Remove unused issuerDB parameters
|
# Remove unused issuerDB parameters except options
|
||||||
foreach my $k ( keys %$issuerParameters ) {
|
foreach my $k ( keys %$issuerParameters ) {
|
||||||
unless ( $conf->{ $k . "Activation" } ) {
|
unless ( $conf->{ $k . "Activation" } ) {
|
||||||
delete $conf->{$_} foreach ( @{ $issuerParameters->{$k} } );
|
foreach ( @{ $issuerParameters->{$k} } ) {
|
||||||
|
delete $conf->{$_} unless ( $_ =~ /^issuers/ );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ use constant HANDLERSECTION => "handler";
|
||||||
use constant MANAGERSECTION => "manager";
|
use constant MANAGERSECTION => "manager";
|
||||||
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
|
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
|
||||||
use constant APPLYSECTION => "apply";
|
use constant APPLYSECTION => "apply";
|
||||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
||||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent|RequirePKCE|Public)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?)?|y(?:Deleted|Other))|AjaxHook)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|d(?:isablePersistentStorage|biDynamicHashEnabled|ontCompactConf)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|rest(?:(?:Session|Config)Server|ExportSecretKeys)|br(?:owsersDontStorePassword|uteForceProtection)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
|
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|AllowOffline|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?)?|y(?:Deleted|Other))|AjaxHook)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|d(?:isablePersistentStorage|biDynamicHashEnabled|ontCompactConf)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|br(?:owsersDontStorePassword|uteForceProtection)|(?:(?:globalLogout|active)Tim|wsdlServ)er|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs))$/;
|
||||||
|
|
||||||
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
|
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,8 @@ sub defaultValues {
|
||||||
'failedLoginNumber' => 5,
|
'failedLoginNumber' => 5,
|
||||||
'favAppsMaxNumber' => 3,
|
'favAppsMaxNumber' => 3,
|
||||||
'formTimeout' => 120,
|
'formTimeout' => 120,
|
||||||
|
'globalLogoutRule' => 0,
|
||||||
|
'globalLogoutTimer' => 1,
|
||||||
'globalStorage' => 'Apache::Session::File',
|
'globalStorage' => 'Apache::Session::File',
|
||||||
'globalStorageOptions' => {
|
'globalStorageOptions' => {
|
||||||
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
||||||
|
@ -167,21 +169,25 @@ sub defaultValues {
|
||||||
'multiValuesSeparator' => '; ',
|
'multiValuesSeparator' => '; ',
|
||||||
'mySessionAuthorizedRWKeys' =>
|
'mySessionAuthorizedRWKeys' =>
|
||||||
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
|
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
|
||||||
'notificationServerPOST' => 1,
|
'notificationDefaultCond' => '',
|
||||||
|
'notificationServerPOST' => 1,
|
||||||
'notificationServerSentAttributes' =>
|
'notificationServerSentAttributes' =>
|
||||||
'uid reference date title subtitle text check',
|
'uid reference date title subtitle text check',
|
||||||
'notificationStorage' => 'File',
|
'notificationStorage' => 'File',
|
||||||
'notificationStorageOptions' => {
|
'notificationStorageOptions' => {
|
||||||
'dirName' => '/var/lib/lemonldap-ng/notifications'
|
'dirName' => '/var/lib/lemonldap-ng/notifications'
|
||||||
},
|
},
|
||||||
'notificationWildcard' => 'allusers',
|
'notificationWildcard' => 'allusers',
|
||||||
'notifyDeleted' => 1,
|
'notifyDeleted' => 1,
|
||||||
'nullAuthnLevel' => 0,
|
'nullAuthnLevel' => 0,
|
||||||
'oidcAuthnLevel' => 1,
|
'oidcAuthnLevel' => 1,
|
||||||
'oidcRPCallbackGetParam' => 'openidconnectcallback',
|
'oidcRPCallbackGetParam' => 'openidconnectcallback',
|
||||||
'oidcRPStateTimeout' => 600,
|
'oidcRPStateTimeout' => 600,
|
||||||
'oidcServiceAllowAuthorizationCodeFlow' => 1,
|
'oidcServiceAccessTokenExpiration' => 3600,
|
||||||
'oidcServiceMetaDataAuthnContext' => {
|
'oidcServiceAllowAuthorizationCodeFlow' => 1,
|
||||||
|
'oidcServiceAuthorizationCodeExpiration' => 60,
|
||||||
|
'oidcServiceIDTokenExpiration' => 3600,
|
||||||
|
'oidcServiceMetaDataAuthnContext' => {
|
||||||
'loa-1' => 1,
|
'loa-1' => 1,
|
||||||
'loa-2' => 2,
|
'loa-2' => 2,
|
||||||
'loa-3' => 3,
|
'loa-3' => 3,
|
||||||
|
@ -198,6 +204,7 @@ sub defaultValues {
|
||||||
'oidcServiceMetaDataRegistrationURI' => 'register',
|
'oidcServiceMetaDataRegistrationURI' => 'register',
|
||||||
'oidcServiceMetaDataTokenURI' => 'token',
|
'oidcServiceMetaDataTokenURI' => 'token',
|
||||||
'oidcServiceMetaDataUserInfoURI' => 'userinfo',
|
'oidcServiceMetaDataUserInfoURI' => 'userinfo',
|
||||||
|
'oidcServiceOfflineSessionExpiration' => 2592000,
|
||||||
'openIdAuthnLevel' => 1,
|
'openIdAuthnLevel' => 1,
|
||||||
'openIdExportedVars' => {},
|
'openIdExportedVars' => {},
|
||||||
'openIdIDPList' => '0;',
|
'openIdIDPList' => '0;',
|
||||||
|
|
|
@ -22,12 +22,12 @@ our $specialNodeHash = {
|
||||||
};
|
};
|
||||||
|
|
||||||
our $doubleHashKeys = 'issuerDBGetParameters';
|
our $doubleHashKeys = 'issuerDBGetParameters';
|
||||||
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|c(?:as(?:StorageOption|Attribute)|ustomAddParam|ombModule)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|S(?:MTPTLSOpts|SLVarIf))';
|
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|ombModule)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|S(?:MTPTLSOpts|SLVarIf))';
|
||||||
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
|
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
|
||||||
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|ExportedVars)';
|
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|ExportedVars)';
|
||||||
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
|
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
|
||||||
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
|
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
|
||||||
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|Logout(?:SessionRequired|Type|Url)|R(?:e(?:directUris|quirePKCE)|ule)|P(?:ostLogoutRedirectUris|ublic)|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|ExportedVars)';
|
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:(?:uthorizationCode|ccessToken)Expiration|llowOffline)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|ExportedVars)';
|
||||||
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
|
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
|
||||||
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|ExportedAttributes|XML)';
|
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|ExportedAttributes|XML)';
|
||||||
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
|
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
|
||||||
|
@ -68,6 +68,6 @@ our $issuerParameters = {
|
||||||
issuerOptions => [qw(issuersTimeout)],
|
issuerOptions => [qw(issuersTimeout)],
|
||||||
};
|
};
|
||||||
our $samlServiceParameters = [qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlMetadataForceUTF8 samlStorage samlStorageOptions samlRelayStateTimeout samlUseQueryStringSpecific samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive samlOverrideIDPEntityID)];
|
our $samlServiceParameters = [qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlMetadataForceUTF8 samlStorage samlStorageOptions samlRelayStateTimeout samlUseQueryStringSpecific samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive samlOverrideIDPEntityID)];
|
||||||
our $oidcServiceParameters = [qw(oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataIntrospectionURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcStorage oidcStorageOptions)];
|
our $oidcServiceParameters = [qw(oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataIntrospectionURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcServiceAuthorizationCodeExpiration oidcServiceAccessTokenExpiration oidcServiceIDTokenExpiration oidcServiceOfflineSessionExpiration oidcStorage oidcStorageOptions)];
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -21,6 +21,7 @@ $hash = \&Digest::SHA::sha256;
|
||||||
use constant HMAC_LENGTH => 32;
|
use constant HMAC_LENGTH => 32;
|
||||||
use constant IV_LENGTH => 16;
|
use constant IV_LENGTH => 16;
|
||||||
|
|
||||||
|
# Build initialization vector subroutine
|
||||||
BEGIN {
|
BEGIN {
|
||||||
eval { require Crypt::URandom; Crypt::URandom::urandom(IV_LENGTH) };
|
eval { require Crypt::URandom; Crypt::URandom::urandom(IV_LENGTH) };
|
||||||
if ($@) {
|
if ($@) {
|
||||||
|
|
|
@ -7,8 +7,9 @@ use JSON qw(from_json to_json);
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
|
|
||||||
sub newNotification {
|
sub newNotification {
|
||||||
my ( $self, $jsonString ) = @_;
|
my ( $self, $jsonString, $defaultCond ) = @_;
|
||||||
my $json;
|
my $json;
|
||||||
|
$defaultCond ||= '';
|
||||||
eval { $json = from_json( $jsonString, { allow_nonref => 1 } ) };
|
eval { $json = from_json( $jsonString, { allow_nonref => 1 } ) };
|
||||||
if ( my $err = $@ ) {
|
if ( my $err = $@ ) {
|
||||||
eval { $self->logger->error("Unable to decode JSON file: $err") };
|
eval { $self->logger->error("Unable to decode JSON file: $err") };
|
||||||
|
@ -35,8 +36,16 @@ sub newNotification {
|
||||||
}
|
}
|
||||||
push @data, $tmp;
|
push @data, $tmp;
|
||||||
}
|
}
|
||||||
push @data, ( $notif->{condition} // '' );
|
|
||||||
push @notifs, [ @data, $jsonString ];
|
unless ( exists $notif->{condition} ) {
|
||||||
|
$self->userLogger->info(
|
||||||
|
"Set defaultCondition ($defaultCond) for notification $notif->{reference}");
|
||||||
|
$notif->{condition} = $defaultCond;
|
||||||
|
}
|
||||||
|
|
||||||
|
push @data, ( $notif->{condition} );
|
||||||
|
my $body = to_json($notif);
|
||||||
|
push @notifs, [ @data, $body ];
|
||||||
}
|
}
|
||||||
my $count;
|
my $count;
|
||||||
foreach (@notifs) {
|
foreach (@notifs) {
|
||||||
|
|
|
@ -18,7 +18,8 @@ has parser => (
|
||||||
# @param $xml XML string containing notification
|
# @param $xml XML string containing notification
|
||||||
# @return number of notifications done
|
# @return number of notifications done
|
||||||
sub newNotification {
|
sub newNotification {
|
||||||
my ( $self, $xml ) = @_;
|
my ( $self, $xml, $defaultCond ) = @_;
|
||||||
|
$defaultCond ||= '';
|
||||||
eval { $xml = $self->parser->parse_string($xml) };
|
eval { $xml = $self->parser->parse_string($xml) };
|
||||||
if ( my $err = $@ ) {
|
if ( my $err = $@ ) {
|
||||||
eval { $self->logger->error("Unable to read XML file : $err") };
|
eval { $self->logger->error("Unable to read XML file : $err") };
|
||||||
|
@ -53,7 +54,12 @@ sub newNotification {
|
||||||
if ( $tmp = $notif->getAttribute($_) ) {
|
if ( $tmp = $notif->getAttribute($_) ) {
|
||||||
push @data, $tmp;
|
push @data, $tmp;
|
||||||
}
|
}
|
||||||
else { push @data, ""; }
|
else {
|
||||||
|
$self->userLogger->info(
|
||||||
|
"Set defaultCondition ($defaultCond) for notification " . $notif->{reference}
|
||||||
|
);
|
||||||
|
push @data, $defaultCond;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $result = XML::LibXML::Document->new( $version, $encoding );
|
my $result = XML::LibXML::Document->new( $version, $encoding );
|
||||||
|
|
|
@ -18,7 +18,7 @@ our $VERSION = '2.1.0';
|
||||||
# Not that only functions, not methods, can be written here
|
# Not that only functions, not methods, can be written here
|
||||||
our $functions =
|
our $functions =
|
||||||
[
|
[
|
||||||
qw(&checkLogonHours &date &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6)
|
qw(&checkLogonHours &date &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri)
|
||||||
];
|
];
|
||||||
|
|
||||||
## @function boolean checkLogonHours(string logon_hours, string syntax, string time_correction, boolean default_access)
|
## @function boolean checkLogonHours(string logon_hours, string syntax, string time_correction, boolean default_access)
|
||||||
|
@ -72,6 +72,36 @@ sub checkLogonHours {
|
||||||
return substr( $base2_logon_hours, $hourpos, 1 );
|
return substr( $base2_logon_hours, $hourpos, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @function integer listMatch
|
||||||
|
# Test if a value is found in a collection
|
||||||
|
# @param $list Can be a hash, array or string including the separator
|
||||||
|
# @param $value string The value to search for
|
||||||
|
# @param $ignorecase boolean Be case insensitive
|
||||||
|
# @return 1 if the value was found, 0 else
|
||||||
|
# NOTE: this function is not exported directly in this module because we don't
|
||||||
|
# want the usr to have to worry about separator. Is is wrapped in a closure in
|
||||||
|
# Jail.pm
|
||||||
|
sub listMatch {
|
||||||
|
my ( $sep, $list, $value, $ignorecase ) = @_;
|
||||||
|
my $flags = $ignorecase ? 'i' : '';
|
||||||
|
my @a;
|
||||||
|
if ( ref($list) eq "ARRAY" ) {
|
||||||
|
@a = @{$list};
|
||||||
|
}
|
||||||
|
elsif ( ref($list) eq "HASH" ) {
|
||||||
|
@a = keys %{$list};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@a = split $sep, $list;
|
||||||
|
}
|
||||||
|
if ( grep /(?$flags)^\Q$value\E$/, @a ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
## @function integer date
|
## @function integer date
|
||||||
# Get current local date
|
# Get current local date
|
||||||
# @param $gmt optional boolean To return GMT date (default is local date)
|
# @param $gmt optional boolean To return GMT date (default is local date)
|
||||||
|
@ -187,4 +217,11 @@ sub isInNet6 {
|
||||||
return net6( $ip, $bits ) eq net6( $net, $bits ) ? 1 : 0;
|
return net6( $ip, $bits ) eq net6( $net, $bits ) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub varIsInUri {
|
||||||
|
my ( $uri, $wanteduri, $attribute, $restricted ) = @_;
|
||||||
|
return $restricted
|
||||||
|
? $uri =~ /$wanteduri$attribute$/o
|
||||||
|
: $uri =~ /$wanteduri$attribute/o;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -24,6 +24,13 @@ sub setTypes {
|
||||||
( $type eq 'global' ? 'SSO' : ucfirst($type) );
|
( $type eq 'global' ? 'SSO' : ucfirst($type) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $offlinebackend = $self->{sessionTypes}->{oidc} ? 'oidc' : 'global';
|
||||||
|
$self->{sessionTypes}->{offline}->{module} =
|
||||||
|
$self->{sessionTypes}->{$offlinebackend}->{module};
|
||||||
|
$self->{sessionTypes}->{offline}->{options} =
|
||||||
|
$self->{sessionTypes}->{$offlinebackend}->{options};
|
||||||
|
$self->{sessionTypes}->{offline}->{kind} = "OIDCI";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub separator {
|
sub separator {
|
||||||
|
|
250
lemonldap-ng-common/scripts/convertSessions
Executable file
250
lemonldap-ng-common/scripts/convertSessions
Executable file
|
@ -0,0 +1,250 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
#=============================================================================
|
||||||
|
# LemonLDAP::NG session conversion tool
|
||||||
|
#
|
||||||
|
# This script lets an administrator migrate existing sessions from one backend
|
||||||
|
# to another. It is mostly useful when run on persistant sessions, but it can be
|
||||||
|
# useful in some other cases too, such as OIDC Offline sessions
|
||||||
|
#
|
||||||
|
# This is part of LemonLDAP::NG product, released under GPL
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
use Lemonldap::NG::Common::Apache::Session;
|
||||||
|
use Lemonldap::NG::Common::Session;
|
||||||
|
use Config::IniFiles;
|
||||||
|
use strict;
|
||||||
|
use Getopt::Std;
|
||||||
|
$Getopt::Std::STANDARD_HELP_VERSION = 1;
|
||||||
|
|
||||||
|
our $VERSION = "2.0.6";
|
||||||
|
|
||||||
|
# Options
|
||||||
|
# -d: debug mode
|
||||||
|
# -c: configuration file
|
||||||
|
# -i: ignore errors
|
||||||
|
my $opts = {};
|
||||||
|
getopts( 'dic:', $opts );
|
||||||
|
|
||||||
|
my $debug = $opts->{d};
|
||||||
|
my $config_file = $opts->{c};
|
||||||
|
my $ignore_errors = $opts->{i};
|
||||||
|
my $nb_converted = 0;
|
||||||
|
my $nb_error = 0;
|
||||||
|
|
||||||
|
sub HELP_MESSAGE {
|
||||||
|
my $OUT = shift;
|
||||||
|
print $OUT <<END_MESSAGE;
|
||||||
|
|
||||||
|
$0 [-di] -c config_file.ini
|
||||||
|
|
||||||
|
-d Debug mode
|
||||||
|
-i Ignore errors
|
||||||
|
|
||||||
|
This script converts sessions in between the two backends specified in the configuration file
|
||||||
|
The configuration file must contain the following (adjust to your environment):
|
||||||
|
|
||||||
|
[sessions_from]
|
||||||
|
storageModule = Apache::Session::File
|
||||||
|
storageModuleOptions = { \\
|
||||||
|
'Directory' => '/var/lib/lemonldap-ng/sessions', \\
|
||||||
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock', \\
|
||||||
|
}
|
||||||
|
# Only convert some session types
|
||||||
|
# sessionKind = Persistent, SSO
|
||||||
|
|
||||||
|
[sessions_to]
|
||||||
|
storageModule = Apache::Session::Browseable::Postgres
|
||||||
|
storageModuleOptions = { \\
|
||||||
|
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \\
|
||||||
|
'UserName' => 'lemonldaplogin', \\
|
||||||
|
'Password' => 'lemonldappw', \\
|
||||||
|
'Commit' => 1, \\
|
||||||
|
'Index' => 'ipAddr _whatToTrace user', \\
|
||||||
|
'TableName' => 'sessions', \\
|
||||||
|
}
|
||||||
|
|
||||||
|
END_MESSAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ($config_file) {
|
||||||
|
HELP_MESSAGE( \*STDERR );
|
||||||
|
die "You must provide the -c option";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $inicfg =
|
||||||
|
Config::IniFiles->new( -file => $config_file, -allowcontinue => 1 );
|
||||||
|
my $cfg = {};
|
||||||
|
|
||||||
|
die "Could not read configuration file" unless $inicfg;
|
||||||
|
|
||||||
|
for my $section (qw/sessions_from sessions_to/) {
|
||||||
|
die "Could not find section $section in configuration file $config_file"
|
||||||
|
unless $inicfg->SectionExists($section);
|
||||||
|
|
||||||
|
# Load section parameters
|
||||||
|
my $r;
|
||||||
|
foreach ( $inicfg->Parameters($section) ) {
|
||||||
|
$r->{$_} = $inicfg->val( $section, $_ );
|
||||||
|
|
||||||
|
# Remove spaces before and after value (#1488)
|
||||||
|
$r->{$_} =~ s/^\s*(.+?)\s*/$1/;
|
||||||
|
if ( $r->{$_} =~ /^[{\[].*[}\]]$/ || $r->{$_} =~ /^sub\s*{.*}$/ ) {
|
||||||
|
eval "\$r->{$_} = $r->{$_}";
|
||||||
|
if ($@) {
|
||||||
|
print $@;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cfg->{$section} = $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $backendFrom;
|
||||||
|
my $backendTo;
|
||||||
|
my @sessionKindOnly;
|
||||||
|
if ( $cfg->{sessions_from}->{sessionKind} ) {
|
||||||
|
@sessionKindOnly = split /\W+/, $cfg->{sessions_from}->{sessionKind};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $cfg->{sessions_from}->{storageModule} ) {
|
||||||
|
$backendFrom = $cfg->{sessions_from}->{storageModuleOptions};
|
||||||
|
$backendFrom->{backend} = $cfg->{sessions_from}->{storageModule};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die
|
||||||
|
"[sessions_from] configuration section does not declare a storageModule";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $cfg->{sessions_to}->{storageModule} ) {
|
||||||
|
$backendTo = $cfg->{sessions_to}->{storageModuleOptions};
|
||||||
|
$backendTo->{backend} = $cfg->{sessions_to}->{storageModule};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "[sessions_to] configuration section does not declare a storageModule";
|
||||||
|
}
|
||||||
|
|
||||||
|
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
|
||||||
|
$backendFrom,
|
||||||
|
sub {
|
||||||
|
my $entry = shift;
|
||||||
|
my $id = shift;
|
||||||
|
|
||||||
|
print "Processing session $id\n" if $debug;
|
||||||
|
my $s = Lemonldap::NG::Common::Session->new( {
|
||||||
|
storageModule => $backendTo->{backend},
|
||||||
|
storageModuleOptions => $backendTo,
|
||||||
|
id => $id,
|
||||||
|
info => $entry,
|
||||||
|
force => 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
# If filtering sessionKind
|
||||||
|
if (@sessionKindOnly) {
|
||||||
|
|
||||||
|
unless ( grep { $_ eq $entry->{_session_kind} } @sessionKindOnly ) {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $s->error ) {
|
||||||
|
die "Error encountered on session $id" unless $ignore_errors;
|
||||||
|
$nb_error += 1;
|
||||||
|
print "Error converting session $id : " . $s->error . "\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "Session $id successfully converted\n" if $debug;
|
||||||
|
$nb_converted += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
print "$nb_converted sessions have been converted\n";
|
||||||
|
|
||||||
|
print "$nb_error errors encountered during conversion\n" if $nb_error;
|
||||||
|
|
||||||
|
my $exit = $nb_error ? 1 : 0;
|
||||||
|
exit $exit;
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
=encoding utf8
|
||||||
|
|
||||||
|
convertSessions - A tool to convert Lemonldap::NG sessions between storage backends.
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
convertSession [-di] -c parameters.ini
|
||||||
|
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
convertConfig is a command line tool to migrate all sessions stored
|
||||||
|
in a source backend (sessions_from), into a new backend (sessions_to).
|
||||||
|
|
||||||
|
It requires a special configuration file in which you must list the source
|
||||||
|
and destination backend modules and parameters.
|
||||||
|
|
||||||
|
Sessions will not be deleted from the source backend. Existing sessions in the
|
||||||
|
destination backend will be kept, unless they have the same session ID as a
|
||||||
|
session in the source backend. In that case, the source will overwrite the
|
||||||
|
destination.
|
||||||
|
|
||||||
|
|
||||||
|
=head1 CONFIGURATION FILE FORMAT
|
||||||
|
|
||||||
|
The configuration file needs two sections to describe the source and destination backends
|
||||||
|
|
||||||
|
Here is an example
|
||||||
|
|
||||||
|
[sessions_from]
|
||||||
|
storageModule = Apache::Session::File
|
||||||
|
storageModuleOptions = { \
|
||||||
|
'Directory' => '/var/lib/lemonldap-ng/sessions', \
|
||||||
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock', \
|
||||||
|
}
|
||||||
|
# Only migrate some session types
|
||||||
|
# sessionKind = Persistent, SSO
|
||||||
|
|
||||||
|
[sessions_to]
|
||||||
|
storageModule = Apache::Session::Browseable::Postgres
|
||||||
|
storageModuleOptions = { \
|
||||||
|
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \
|
||||||
|
'UserName' => 'lemonldaplogin', \
|
||||||
|
'Password' => 'lemonldappw', \
|
||||||
|
'Commit' => 1, \
|
||||||
|
'Index' => 'ipAddr _whatToTrace user', \
|
||||||
|
'TableName' => 'sessions', \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
The C<sessionKind> parameter may be used to filter only some session types.
|
||||||
|
|
||||||
|
Thanks to this, you can use this script to migrate from one database holding
|
||||||
|
all your sessions to separate tables from each session type.
|
||||||
|
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<http://lemonldap-ng.org/>
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item Maxime Besson, E<lt>maxime.besson@worteks.comE<gt>
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 BUG REPORT
|
||||||
|
|
||||||
|
Use OW2 system to report bug or ask for features:
|
||||||
|
L<https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues>
|
||||||
|
|
||||||
|
=head1 DOWNLOAD
|
||||||
|
|
||||||
|
Lemonldap::NG is available at
|
||||||
|
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
||||||
|
|
|
@ -52,6 +52,7 @@ t/61-Lemonldap-NG-Handler-PSGI-Server.t
|
||||||
t/62-Lemonldap-NG-Handler-Nginx.t
|
t/62-Lemonldap-NG-Handler-Nginx.t
|
||||||
t/63-Lemonldap-NG-Handler-PSGI-Try.t
|
t/63-Lemonldap-NG-Handler-PSGI-Try.t
|
||||||
t/64-Lemonldap-NG-Handler-PSGI-DevOps.t
|
t/64-Lemonldap-NG-Handler-PSGI-DevOps.t
|
||||||
|
t/65-Lemonldap-NG-Handler-Nginx-ServiceToken.t
|
||||||
t/65-Lemonldap-NG-Handler-PSGI-ServiceToken.t
|
t/65-Lemonldap-NG-Handler-PSGI-ServiceToken.t
|
||||||
t/66-Lemonldap-NG-Handler-PSGI-wildcard.t
|
t/66-Lemonldap-NG-Handler-PSGI-wildcard.t
|
||||||
t/67-Lemonldap-NG-Handler-PSGI-vhostoptions.t
|
t/67-Lemonldap-NG-Handler-PSGI-vhostoptions.t
|
||||||
|
@ -63,3 +64,4 @@ t/lmConf-1.json
|
||||||
t/sessions/lock/Apache-Session-f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock
|
t/sessions/lock/Apache-Session-f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock
|
||||||
t/test-psgi-lib.pm
|
t/test-psgi-lib.pm
|
||||||
t/test.pm
|
t/test.pm
|
||||||
|
t/Time-Fake.pm
|
||||||
|
|
|
@ -37,6 +37,12 @@ my %builder = (
|
||||||
},
|
},
|
||||||
psgi => sub {
|
psgi => sub {
|
||||||
return sub {
|
return sub {
|
||||||
|
|
||||||
|
# Fix PATH_INFO when using Nginx with default uwsgi_params
|
||||||
|
# See #2031
|
||||||
|
( $_[0]->{PATH_INFO} ) =
|
||||||
|
$_[0]->{REQUEST_URI} =~ /^(?:\Q$_[0]->{SCRIPT_NAME}\E)?([^?]*)/;
|
||||||
|
|
||||||
my $script = $_[0]->{SCRIPT_FILENAME};
|
my $script = $_[0]->{SCRIPT_FILENAME};
|
||||||
return $_apps{$script}->(@_) if ( $_apps{$script} );
|
return $_apps{$script}->(@_) if ( $_apps{$script} );
|
||||||
$_apps{$script} = do $script;
|
$_apps{$script} = do $script;
|
||||||
|
@ -44,7 +50,7 @@ my %builder = (
|
||||||
die "Unable to load $_[0]->{SCRIPT_FILENAME}";
|
die "Unable to load $_[0]->{SCRIPT_FILENAME}";
|
||||||
}
|
}
|
||||||
return $_apps{$script}->(@_);
|
return $_apps{$script}->(@_);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,60 @@ use strict;
|
||||||
|
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
|
|
||||||
|
sub retrieveSession {
|
||||||
|
my ( $class, $req, $id ) = @_;
|
||||||
|
my ($offlineId) = $id =~ /^O-(.*)/;
|
||||||
|
|
||||||
|
# Retrieve regular session if this is not an offline access token
|
||||||
|
unless ($offlineId) {
|
||||||
|
return $class->Lemonldap::NG::Handler::Main::retrieveSession( $req,
|
||||||
|
$id );
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2. Get the session from cache or backend
|
||||||
|
my $session = $req->data->{session} = (
|
||||||
|
Lemonldap::NG::Common::Session->new( {
|
||||||
|
storageModule => $class->tsv->{oidcStorageModule},
|
||||||
|
storageModuleOptions => $class->tsv->{oidcStorageOptions},
|
||||||
|
cacheModule => $class->tsv->{sessionCacheModule},
|
||||||
|
cacheModuleOptions => $class->tsv->{sessionCacheOptions},
|
||||||
|
id => $offlineId,
|
||||||
|
kind => "OIDCI",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
unless ( $session->error ) {
|
||||||
|
|
||||||
|
$class->data( $session->data );
|
||||||
|
$class->logger->debug("Get session $offlineId from Handler::Main::Run");
|
||||||
|
|
||||||
|
# Verify that session is valid
|
||||||
|
$class->logger->error(
|
||||||
|
"_utime is not defined. This should not happen. Check if it is well transmitted to handler"
|
||||||
|
) unless $session->data->{_utime};
|
||||||
|
|
||||||
|
my $ttl = $class->tsv->{timeout} - time + $session->data->{_utime};
|
||||||
|
$class->logger->debug( "Session TTL = " . $ttl );
|
||||||
|
|
||||||
|
if ( time - $session->data->{_utime} > $class->tsv->{timeout} ) {
|
||||||
|
$class->logger->info("Session $id expired");
|
||||||
|
|
||||||
|
# Clean cached data
|
||||||
|
$class->data( {} );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $session->data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$class->logger->info("Session $offlineId can't be retrieved");
|
||||||
|
$class->logger->info( $session->error );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub fetchId {
|
sub fetchId {
|
||||||
my ( $class, $req ) = @_;
|
my ( $class, $req ) = @_;
|
||||||
|
|
||||||
|
@ -21,10 +75,16 @@ sub fetchId {
|
||||||
|
|
||||||
# Get access token session
|
# Get access token session
|
||||||
my $infos = $class->getOIDCInfos($access_token);
|
my $infos = $class->getOIDCInfos($access_token);
|
||||||
|
# If this token is tied to a regular session ID
|
||||||
if ( my $_session_id = $infos->{user_session_id} ) {
|
if ( my $_session_id = $infos->{user_session_id} ) {
|
||||||
$class->logger->debug( 'Get user session id ' . $_session_id );
|
$class->logger->debug( 'Get user session id ' . $_session_id );
|
||||||
return $_session_id;
|
return $_session_id;
|
||||||
}
|
}
|
||||||
|
# If this token is tied to an Offline session
|
||||||
|
if ( my $_session_id = $infos->{offline_session_id} ) {
|
||||||
|
$class->logger->debug( 'Get offline session id ' . $_session_id );
|
||||||
|
return "O-$_session_id";
|
||||||
|
}
|
||||||
|
|
||||||
return $class->Lemonldap::NG::Handler::Main::fetchId($req);
|
return $class->Lemonldap::NG::Handler::Main::fetchId($req);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +110,8 @@ sub getOIDCInfos {
|
||||||
unless ( $oidcSession->error ) {
|
unless ( $oidcSession->error ) {
|
||||||
$class->logger->debug("Get OIDC session $id");
|
$class->logger->debug("Get OIDC session $id");
|
||||||
|
|
||||||
$infos->{user_session_id} = $oidcSession->data->{user_session_id};
|
$infos->{user_session_id} = $oidcSession->data->{user_session_id};
|
||||||
|
$infos->{offline_session_id} = $oidcSession->data->{offline_session_id};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$class->logger->info("OIDC Session $id can't be retrieved");
|
$class->logger->info("OIDC Session $id can't be retrieved");
|
||||||
|
|
|
@ -56,10 +56,10 @@ sub fetchId {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Send service headers if exist
|
# Send service headers to protected application if exist
|
||||||
if (%serviceHeaders) {
|
if (%serviceHeaders) {
|
||||||
$class->logger->debug("Append service header(s)...");
|
$class->logger->info("Append service header(s)...");
|
||||||
$class->set_header_out( $req, %serviceHeaders );
|
$class->set_header_in( $req, %serviceHeaders );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $_session_id;
|
return $_session_id;
|
||||||
|
|
|
@ -99,9 +99,10 @@ sub portalConsts {
|
||||||
'93' => 'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
|
'93' => 'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
|
||||||
'94' => 'PE_ISSUERMISSINGREQATTR',
|
'94' => 'PE_ISSUERMISSINGREQATTR',
|
||||||
'95' => 'PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED',
|
'95' => 'PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED',
|
||||||
'96' => 'PE_RESETCERTIFICATE_INVALID',
|
'96' => 'PE_BADOTP',
|
||||||
'97' => 'PE_RESETCERTIFICATE_FORMEMPTY',
|
'97' => 'PE_RESETCERTIFICATE_FORMEMPTY',
|
||||||
'98' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
|
'98' => 'PE_RESETCERTIFICATE_FIRSTACCESS',
|
||||||
|
'99' => 'PE_RESETCERTIFICATE_INVALID'
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,11 @@ BEGIN {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has customFunctions => ( is => 'rw', isa => 'Maybe[Str]' );
|
has customFunctions => ( is => 'rw', isa => 'Maybe[Str]' );
|
||||||
has useSafeJail => ( is => 'rw', isa => 'Maybe[Int]' );
|
has useSafeJail => ( is => 'rw', isa => 'Maybe[Int]' );
|
||||||
has jail => ( is => 'rw' );
|
has multiValuesSeparator => ( is => 'rw', isa => 'Maybe[Str]' );
|
||||||
has error => ( is => 'rw' );
|
has jail => ( is => 'rw' );
|
||||||
|
has error => ( is => 'rw' );
|
||||||
|
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
our @builtCustomFunctions;
|
our @builtCustomFunctions;
|
||||||
|
@ -88,7 +89,18 @@ sub build_jail {
|
||||||
$self->jail->share_from( 'Lemonldap::NG::Common::Safelib',
|
$self->jail->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||||
$Lemonldap::NG::Common::Safelib::functions );
|
$Lemonldap::NG::Common::Safelib::functions );
|
||||||
|
|
||||||
$self->jail->share_from( __PACKAGE__, [ @builtCustomFunctions, '&encrypt', '&token' ] );
|
# Closure for listMatch
|
||||||
|
{
|
||||||
|
no warnings 'redefine';
|
||||||
|
*listMatch = sub {
|
||||||
|
return Lemonldap::NG::Common::Safelib::listMatch(
|
||||||
|
$self->multiValuesSeparator, @_ );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->jail->share_from( __PACKAGE__,
|
||||||
|
[ @builtCustomFunctions, '&encrypt', '&token', '&listMatch' ] );
|
||||||
|
|
||||||
$self->jail->share_from( 'MIME::Base64', ['&encode_base64'] );
|
$self->jail->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||||
|
|
||||||
#$self->jail->share_from( 'Lemonldap::NG::Handler::Main', ['$_v'] );
|
#$self->jail->share_from( 'Lemonldap::NG::Handler::Main', ['$_v'] );
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Scalar::Util qw(weaken);
|
||||||
|
|
||||||
use constant UNPROTECT => 1;
|
use constant UNPROTECT => 1;
|
||||||
use constant SKIP => 2;
|
use constant SKIP => 2;
|
||||||
|
use constant MAYSKIP => 3;
|
||||||
|
|
||||||
our @_onReload;
|
our @_onReload;
|
||||||
|
|
||||||
|
@ -179,8 +180,9 @@ sub jailInit {
|
||||||
my ( $class, $conf ) = @_;
|
my ( $class, $conf ) = @_;
|
||||||
|
|
||||||
$class->tsv->{jail} = Lemonldap::NG::Handler::Main::Jail->new( {
|
$class->tsv->{jail} = Lemonldap::NG::Handler::Main::Jail->new( {
|
||||||
useSafeJail => $conf->{useSafeJail},
|
useSafeJail => $conf->{useSafeJail},
|
||||||
customFunctions => $conf->{customFunctions},
|
customFunctions => $conf->{customFunctions},
|
||||||
|
multiValuesSeparator => $conf->{multiValuesSeparator},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$class->tsv->{jail}->build_jail( $class, $conf->{require} );
|
$class->tsv->{jail}->build_jail( $class, $conf->{require} );
|
||||||
|
@ -545,6 +547,9 @@ sub conditionSub {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $mayskip = 0;
|
||||||
|
$mayskip = MAYSKIP if $cond =~ /\bskip\b/;
|
||||||
|
|
||||||
# Replace some strings in condition
|
# Replace some strings in condition
|
||||||
$cond = $class->substitute($cond);
|
$cond = $class->substitute($cond);
|
||||||
my $sub;
|
my $sub;
|
||||||
|
@ -554,7 +559,7 @@ sub conditionSub {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Return sub and protected flag
|
# Return sub and protected flag
|
||||||
return ( $sub, 0 );
|
return ( $sub, $mayskip );
|
||||||
}
|
}
|
||||||
|
|
||||||
## @method arrayref aliasInit
|
## @method arrayref aliasInit
|
||||||
|
@ -589,6 +594,7 @@ sub substitute {
|
||||||
$expr =~ s/\$ENV\{/\$r->{env}->\{/g;
|
$expr =~ s/\$ENV\{/\$r->{env}->\{/g;
|
||||||
$expr =~ s/\$env->\{/\$r->{env}->\{/g;
|
$expr =~ s/\$env->\{/\$r->{env}->\{/g;
|
||||||
$expr =~ s/\$_rulematch\[/\$m->\[/g;
|
$expr =~ s/\$_rulematch\[/\$m->\[/g;
|
||||||
|
$expr =~ s/\bskip\b/q\{999_SKIP\}/g;
|
||||||
|
|
||||||
return $expr;
|
return $expr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,11 @@ sub run {
|
||||||
$class->cleanHeaders($req);
|
$class->cleanHeaders($req);
|
||||||
return $class->OK;
|
return $class->OK;
|
||||||
}
|
}
|
||||||
|
elsif ( $protection == $class->MAYSKIP
|
||||||
|
and $class->grant( $req, $session, $uri, $cond ) eq '999_SKIP' )
|
||||||
|
{
|
||||||
|
return $class->OK;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
@ -441,7 +446,7 @@ sub fetchId {
|
||||||
my $value =
|
my $value =
|
||||||
$lookForHttpCookie
|
$lookForHttpCookie
|
||||||
? ( $t =~ /${cn}http=([^,; ]+)/o ? $1 : 0 )
|
? ( $t =~ /${cn}http=([^,; ]+)/o ? $1 : 0 )
|
||||||
: ( $t =~ /$cn=([^,; ]+)/o ? $1 : 0 );
|
: ( $t =~ /$cn=([^,; ]+)/o ? $1 : 0 );
|
||||||
|
|
||||||
if ( $value && $lookForHttpCookie && $class->tsv->{securedCookie} == 3 ) {
|
if ( $value && $lookForHttpCookie && $class->tsv->{securedCookie} == 3 ) {
|
||||||
$value = $class->tsv->{cipher}->decryptHex( $value, "http" );
|
$value = $class->tsv->{cipher}->decryptHex( $value, "http" );
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# change 'tests => 1' to 'tests => last_test_to_print';
|
# change 'tests => 1' to 'tests => last_test_to_print';
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use Test::More tests => 9;
|
use Test::More tests => 13;
|
||||||
require 't/test.pm';
|
require 't/test.pm';
|
||||||
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
||||||
|
|
||||||
|
@ -18,8 +18,9 @@ my $res;
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
my $jail = Lemonldap::NG::Handler::Main::Jail->new(
|
my $jail = Lemonldap::NG::Handler::Main::Jail->new(
|
||||||
'jail' => undef,
|
'jail' => undef,
|
||||||
'useSafeJail' => 1,
|
'useSafeJail' => 1,
|
||||||
|
'multiValuesSeparator' => '; ',
|
||||||
),
|
),
|
||||||
'new jail object'
|
'new jail object'
|
||||||
);
|
);
|
||||||
|
@ -38,6 +39,18 @@ ok(
|
||||||
ok( $res = &$code, "Function works" );
|
ok( $res = &$code, "Function works" );
|
||||||
ok( $res eq 'dGVzdA==', 'Get good result' );
|
ok( $res eq 'dGVzdA==', 'Get good result' );
|
||||||
|
|
||||||
|
$sub = "sub { return ( listMatch('ABC; DEF; GHI','abc',1) ) }";
|
||||||
|
my $code = $jail->jail_reval($sub);
|
||||||
|
ok( ( defined($code) and ref($code) eq 'CODE' ),
|
||||||
|
'listMatch function is defined' );
|
||||||
|
ok( &$code eq '1', 'Get good result' );
|
||||||
|
|
||||||
|
$sub = "sub { return ( listMatch('ABC; DEF; GHI','ab',1) ) }";
|
||||||
|
my $code = $jail->jail_reval($sub);
|
||||||
|
ok( ( defined($code) and ref($code) eq 'CODE' ),
|
||||||
|
'listMatch function is defined' );
|
||||||
|
ok( &$code eq '0', 'Get good result' );
|
||||||
|
|
||||||
$sub = "sub { return(checkDate('20000000000000','21000000000000')) }";
|
$sub = "sub { return(checkDate('20000000000000','21000000000000')) }";
|
||||||
$code = $jail->jail_reval($sub);
|
$code = $jail->jail_reval($sub);
|
||||||
ok(
|
ok(
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
# change 'tests => 1' to 'tests => last_test_to_print';
|
# change 'tests => 1' to 'tests => last_test_to_print';
|
||||||
|
|
||||||
use Test::More tests => 5;
|
use Test::More tests => 9;
|
||||||
require 't/test.pm';
|
require 't/test.pm';
|
||||||
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
||||||
|
|
||||||
|
@ -16,9 +16,10 @@ BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
my $jail = Lemonldap::NG::Handler::Main::Jail->new(
|
my $jail = Lemonldap::NG::Handler::Main::Jail->new(
|
||||||
'jail' => undef,
|
'jail' => undef,
|
||||||
'useSafeJail' => 0,
|
'useSafeJail' => 0,
|
||||||
'customFunctions' => undef
|
'customFunctions' => undef,
|
||||||
|
'multiValuesSeparator' => '; ',
|
||||||
),
|
),
|
||||||
'new fake jail object'
|
'new fake jail object'
|
||||||
);
|
);
|
||||||
|
@ -41,3 +42,15 @@ my $sub3 = "sub { return(checkDate('20000000000000','21000000000000')) }";
|
||||||
my $checkDate = $jail->jail_reval($sub3);
|
my $checkDate = $jail->jail_reval($sub3);
|
||||||
ok( &$checkDate == "1",
|
ok( &$checkDate == "1",
|
||||||
'checkDate extended function working without Safe Jail' );
|
'checkDate extended function working without Safe Jail' );
|
||||||
|
|
||||||
|
my $sub4 = "sub { return ( listMatch('ABC; DEF; GHI','abc', 1) ) }";
|
||||||
|
my $listMatch = $jail->jail_reval($sub4);
|
||||||
|
ok( ( defined($listMatch) and ref($listMatch) eq 'CODE' ),
|
||||||
|
'listMatch function is defined' );
|
||||||
|
ok( &$listMatch eq '1', 'Get good result' );
|
||||||
|
|
||||||
|
my $sub5 = "sub { return ( listMatch('ABC; DEF; GHI','ab', 1) ) }";
|
||||||
|
my $listMatch = $jail->jail_reval($sub5);
|
||||||
|
ok( ( defined($listMatch) and ref($listMatch) eq 'CODE' ),
|
||||||
|
'listMatch function is defined' );
|
||||||
|
ok( &$listMatch eq '0', 'Get good result' );
|
||||||
|
|
|
@ -8,6 +8,7 @@ require 't/test-psgi-lib.pm';
|
||||||
init('Lemonldap::NG::Handler::PSGI');
|
init('Lemonldap::NG::Handler::PSGI');
|
||||||
|
|
||||||
my $res;
|
my $res;
|
||||||
|
my $SKIPUSER = 0;
|
||||||
|
|
||||||
# Unauthentified query
|
# Unauthentified query
|
||||||
# --------------------
|
# --------------------
|
||||||
|
@ -38,7 +39,45 @@ count(2);
|
||||||
ok( $res = $client->_get( '/user_dwho/', undef, undef, "lemonldap=$sessionId" ),
|
ok( $res = $client->_get( '/user_dwho/', undef, undef, "lemonldap=$sessionId" ),
|
||||||
'Regexp query' );
|
'Regexp query' );
|
||||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> allowed
|
||||||
|
ok(
|
||||||
|
$res =
|
||||||
|
$client->_get( '/test-uri1/dwho', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Authentified query'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, '/test-uri1 -> Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> allowed
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/test-uri2/dwho/dummy', undef, undef, "lemonldap=$sessionId"
|
||||||
|
),
|
||||||
|
'Authentified query'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, '/test-uri2 -> Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok(
|
||||||
|
$res =
|
||||||
|
$client->_get( '/test-uri1/dwho/', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 403, '/test-uri1 -> Code is 403' )
|
||||||
|
or explain( $res->[0], 403 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok(
|
||||||
|
$res =
|
||||||
|
$client->_get( '/test-uri1/dwh', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 403, '/test-uri1 -> Code is 403' )
|
||||||
|
or explain( $res->[0], 403 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
# Denied query
|
# Denied query
|
||||||
|
@ -124,14 +163,25 @@ ok(
|
||||||
);
|
);
|
||||||
count(3);
|
count(3);
|
||||||
|
|
||||||
|
ok( $res = $client->_get( '/skipif/za', undef, 'test1.example.com' ),
|
||||||
|
'Test skip() rule 1' );
|
||||||
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res, 302 );
|
||||||
|
$SKIPUSER = 1;
|
||||||
|
ok( $res = $client->_get( '/skipif/zz', undef, 'test1.example.com' ),
|
||||||
|
'Test skip() rule 2' );
|
||||||
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(4);
|
||||||
|
|
||||||
done_testing( count() );
|
done_testing( count() );
|
||||||
|
|
||||||
clean();
|
clean();
|
||||||
|
|
||||||
sub Lemonldap::NG::Handler::PSGI::handler {
|
sub Lemonldap::NG::Handler::PSGI::handler {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
ok( $req->env->{HTTP_AUTH_USER} eq 'dwho', 'Header is given to app' )
|
unless ($SKIPUSER) {
|
||||||
or explain( $req->env->{HTTP_AUTH_USER}, 'dwho' );
|
ok( $req->env->{HTTP_AUTH_USER} eq 'dwho', 'Header is given to app' )
|
||||||
count(1);
|
or explain( $req->env->{HTTP_AUTH_USER}, 'dwho' );
|
||||||
|
count(1);
|
||||||
|
}
|
||||||
return [ 200, [ 'Content-Type', 'text/plain' ], ['Hello'] ];
|
return [ 200, [ 'Content-Type', 'text/plain' ], ['Hello'] ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,36 @@ ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
|
||||||
or explain( \%h, 'Auth-User => "dwho"' );
|
or explain( \%h, 'Auth-User => "dwho"' );
|
||||||
count(1);
|
count(1);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> allowed
|
||||||
|
ok( $res = $client->_get( '/test-restricted_uri/dwho/', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Authentified query' );
|
||||||
|
ok( $res->[0] == 200, '/test-restricted_uri -> Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok( $res = $client->_get( '/test-restricted_uri/dwho', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query' );
|
||||||
|
ok( $res->[0] == 403, '/test-restricted_uri -> Code is 403' ) or explain( $res->[0], 403 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> allowed
|
||||||
|
ok( $res = $client->_get( '/test-uri2/dwho/dummy', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Authentified query' );
|
||||||
|
ok( $res->[0] == 200, '/test-uri2 -> Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok( $res = $client->_get( '/test-uri1/dwho/', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query' );
|
||||||
|
ok( $res->[0] == 403, '/test-uri1 -> Code is 403' ) or explain( $res->[0], 403 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok( $res = $client->_get( '/test-uri1/dwh', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query' );
|
||||||
|
ok( $res->[0] == 403, '/test-uri1 -> Code is 403' ) or explain( $res->[0], 403 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
# Denied query
|
# Denied query
|
||||||
ok( $res = $client->_get( '/deny', undef, undef, "lemonldap=$sessionId" ),
|
ok( $res = $client->_get( '/deny', undef, undef, "lemonldap=$sessionId" ),
|
||||||
'Denied query' );
|
'Denied query' );
|
||||||
|
|
|
@ -44,6 +44,30 @@ ok( $h{'Headervalue1'} eq 'dwho', 'Headervalue1 is set to "dwho"' )
|
||||||
or explain( \%h, 'Headervalue1 => "dwho"' );
|
or explain( \%h, 'Headervalue1 => "dwho"' );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> allowed
|
||||||
|
ok( $res = $client->_get( '/test-uri1/dwho', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Authentified query' );
|
||||||
|
ok( $res->[0] == 200, '/test-uri1 -> Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> allowed
|
||||||
|
ok( $res = $client->_get( '/test-uri2/dwho/dummy', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Authentified query' );
|
||||||
|
ok( $res->[0] == 200, '/test-uri2 -> Code is 200' ) or explain( $res, 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok( $res = $client->_get( '/test-uri1/dwho/', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query' );
|
||||||
|
ok( $res->[0] == 403, '/test-uri1 -> Code is 403' ) or explain( $res->[0], 403 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Request an URI protected by custom function -> denied
|
||||||
|
ok( $res = $client->_get( '/test-uri1/dwh', undef, undef, "lemonldap=$sessionId" ),
|
||||||
|
'Denied query' );
|
||||||
|
ok( $res->[0] == 403, '/test-uri1 -> Code is 403' ) or explain( $res->[0], 403 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
# Denied query
|
# Denied query
|
||||||
ok( $res = $client->_get( '/deny', undef, undef, "lemonldap=$sessionId" ),
|
ok( $res = $client->_get( '/deny', undef, undef, "lemonldap=$sessionId" ),
|
||||||
'Denied query' );
|
'Denied query' );
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
use Test::More;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
require 't/test-psgi-lib.pm';
|
||||||
|
}
|
||||||
|
|
||||||
|
init(
|
||||||
|
'Lemonldap::NG::Handler::Server::Nginx',
|
||||||
|
{
|
||||||
|
logLevel => 'error',
|
||||||
|
handlerServiceTokenTTL => 120,
|
||||||
|
vhostOptions => {
|
||||||
|
'test1.example.com' => {
|
||||||
|
vhostHttps => 0,
|
||||||
|
vhostPort => 80,
|
||||||
|
vhostMaintenance => 0,
|
||||||
|
vhostServiceTokenTTL => 180,
|
||||||
|
},
|
||||||
|
'test2.example.com' => {
|
||||||
|
vhostHttps => 0,
|
||||||
|
vhostPort => 80,
|
||||||
|
vhostMaintenance => 0,
|
||||||
|
vhostServiceTokenTTL => 300,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exportedHeaders => {
|
||||||
|
'test2.example.com' => {
|
||||||
|
'Auth-User' => '$uid',
|
||||||
|
'empty' => undef,
|
||||||
|
'zero' => "'0'",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
my $res;
|
||||||
|
my $crypt = Lemonldap::NG::Common::Crypto->new('qwertyui');
|
||||||
|
my $token = $crypt->encrypt(
|
||||||
|
join ':', time,
|
||||||
|
$sessionId, 'test1.example.com',
|
||||||
|
'XFromVH=app1-auth.example.com', "serviceHeader1=$sessionId",
|
||||||
|
"serviceHeader2=$sessionId", 'test2.example.com',
|
||||||
|
'*.example.com'
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test1.example.com', "lemonldap=$sessionId",
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 1'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||||
|
count(2);
|
||||||
|
my %headers = @{ $res->[1] };
|
||||||
|
ok( $header{cookie} eq '', 'NO cookie found' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( \%headers );
|
||||||
|
my @headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
my @values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 6, 'Found 6 service headers' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
ok( @values == 6, 'Found 6 service header values' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(3);
|
||||||
|
|
||||||
|
# Waiting
|
||||||
|
Time::Fake->offset("+90s");
|
||||||
|
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test1.example.com', undef,
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 2'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
@values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 6, 'Found 6 service headers' )
|
||||||
|
or print STDERR Data::Dumper::Dumper($res);
|
||||||
|
ok( @values == 6, 'Found 6 service header values' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Waiting
|
||||||
|
Time::Fake->offset("+210s");
|
||||||
|
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test1.example.com', undef,
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 3'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 401 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(1);
|
||||||
|
|
||||||
|
# Waiting
|
||||||
|
Time::Fake->offset("+270s");
|
||||||
|
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test2.example.com', undef,
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 4'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
my %headers = @{ $res->[1] };
|
||||||
|
ok( $headers{'zero'} eq '0', 'Found "zero" header with "0"' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
ok( $headers{'empty'} eq '', 'Found "empty" header without value' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
@values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 6, 'Found 6 service headers' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
ok( @values == 6, 'Found 6 service header values' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
# Waiting
|
||||||
|
Time::Fake->offset("+330s");
|
||||||
|
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test2.example.com', undef,
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 5'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 401 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(1);
|
||||||
|
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test3.example.com', undef,
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 6'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 401 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(1);
|
||||||
|
|
||||||
|
$token = $crypt->encrypt( join ':', time, $sessionId );
|
||||||
|
ok(
|
||||||
|
$res = $client->_get(
|
||||||
|
'/', undef, 'test2.example.com', undef,
|
||||||
|
VHOSTTYPE => 'ServiceToken',
|
||||||
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
|
),
|
||||||
|
'Query with token 7'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 401 );
|
||||||
|
count(2);
|
||||||
|
|
||||||
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
|
count(1);
|
||||||
|
|
||||||
|
done_testing( count() );
|
||||||
|
|
||||||
|
clean();
|
|
@ -8,19 +8,19 @@ init(
|
||||||
'Lemonldap::NG::Handler::Server',
|
'Lemonldap::NG::Handler::Server',
|
||||||
{
|
{
|
||||||
logLevel => 'error',
|
logLevel => 'error',
|
||||||
handlerServiceTokenTTL => 2,
|
handlerServiceTokenTTL => 120,
|
||||||
vhostOptions => {
|
vhostOptions => {
|
||||||
'test1.example.com' => {
|
'test1.example.com' => {
|
||||||
vhostHttps => 0,
|
vhostHttps => 0,
|
||||||
vhostPort => 80,
|
vhostPort => 80,
|
||||||
vhostMaintenance => 0,
|
vhostMaintenance => 0,
|
||||||
vhostServiceTokenTTL => 3,
|
vhostServiceTokenTTL => 180,
|
||||||
},
|
},
|
||||||
'test2.example.com' => {
|
'test2.example.com' => {
|
||||||
vhostHttps => 0,
|
vhostHttps => 0,
|
||||||
vhostPort => 80,
|
vhostPort => 80,
|
||||||
vhostMaintenance => 0,
|
vhostMaintenance => 0,
|
||||||
vhostServiceTokenTTL => 5,
|
vhostServiceTokenTTL => 300,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exportedHeaders => {
|
exportedHeaders => {
|
||||||
|
@ -38,7 +38,7 @@ my $crypt = Lemonldap::NG::Common::Crypto->new('qwertyui');
|
||||||
my $token = $crypt->encrypt(
|
my $token = $crypt->encrypt(
|
||||||
join ':', time,
|
join ':', time,
|
||||||
$sessionId, 'test1.example.com',
|
$sessionId, 'test1.example.com',
|
||||||
'XFromVH=app1-auth.example.com', "serviceHeader1=$sessionId",
|
'XFromVH=app1-auth.example.com', "serviceHeader1=$sessionId","serviceHeader2=$sessionId",
|
||||||
'test2.example.com', '*.example.com'
|
'test2.example.com', '*.example.com'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -48,21 +48,21 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 1'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
my @headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
my @headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
my @values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
my @values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
||||||
ok( @headers == 2, 'Found 2 service headers' )
|
ok( @headers == 3, 'Found 3 service headers' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
ok( @values == 2, 'Found 2 service header values' )
|
ok( @values == 3, 'Found 3 service header values' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
diag 'Waiting';
|
# Waiting
|
||||||
sleep 1;
|
Time::Fake->offset("+90s");
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
|
@ -70,21 +70,21 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 2'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
@headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
@values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
@values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
||||||
ok( @headers == 2, 'Found 2 service headers' )
|
ok( @headers == 3, 'Found 3 service headers' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
ok( @values == 2, 'Found 2 service header values' )
|
ok( @values == 3, 'Found 3 service header values' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
diag 'Waiting';
|
# Waiting
|
||||||
sleep 2;
|
Time::Fake->offset("+210s");
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
|
@ -92,18 +92,18 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 3'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 302, 'Code is 200' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
@headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
ok( @headers == 0, 'NONE service header found' )
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(1);
|
count(1);
|
||||||
|
|
||||||
diag 'Waiting';
|
# Waiting
|
||||||
sleep 1;
|
Time::Fake->offset("+270s");
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
|
@ -111,7 +111,7 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 4'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||||
count(2);
|
count(2);
|
||||||
|
@ -123,16 +123,16 @@ ok( $headers{'empty'} eq '', 'Found "empty" header without value' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
@headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
@values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
@values = grep { /\.example\.com|^$sessionId$/ } @{ $res->[1] };
|
||||||
ok( @headers == 2, 'Found 2 service headers' )
|
ok( @headers == 3, 'Found 3 service headers' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
ok( @values == 2, 'Found 2 service header values' )
|
ok( @values == 3, 'Found 3 service header values' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
diag 'Waiting';
|
# Waiting
|
||||||
sleep 1;
|
Time::Fake->offset("+330s");
|
||||||
|
|
||||||
ok(
|
ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
|
@ -140,12 +140,12 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 5'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
@headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
ok( @headers == 0, 'NONE service header found' )
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(1);
|
count(1);
|
||||||
|
@ -156,12 +156,12 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 6'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
@headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
ok( @headers == 0, 'NONE service header found' )
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(1);
|
count(1);
|
||||||
|
@ -173,12 +173,12 @@ ok(
|
||||||
VHOSTTYPE => 'ServiceToken',
|
VHOSTTYPE => 'ServiceToken',
|
||||||
'HTTP_X_LLNG_TOKEN' => $token,
|
'HTTP_X_LLNG_TOKEN' => $token,
|
||||||
),
|
),
|
||||||
'Query with token'
|
'Query with token 7'
|
||||||
);
|
);
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
@headers = grep { /service|^XFromVH$/ } @{ $res->[1] };
|
@headers = grep { /^serviceHeader\d$|^XFromVH$/ } @{ $res->[1] };
|
||||||
ok( @headers == 0, 'NONE service header found' )
|
ok( @headers == 0, 'NONE service header found' )
|
||||||
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
or print STDERR Data::Dumper::Dumper( $res->[1] );
|
||||||
count(1);
|
count(1);
|
||||||
|
|
|
@ -11,6 +11,11 @@ SKIP: {
|
||||||
if ($@) {
|
if ($@) {
|
||||||
skip 'Cache::Memcached not found', $maintests;
|
skip 'Cache::Memcached not found', $maintests;
|
||||||
}
|
}
|
||||||
|
my $testmemd = new Cache::Memcached { 'servers' => ["127.0.0.1:11211"] };
|
||||||
|
unless ( $testmemd->stats->{hosts} ) {
|
||||||
|
skip 'Memcached not started', $maintests;
|
||||||
|
}
|
||||||
|
|
||||||
eval { require Apache::Session::Generate::MD5; };
|
eval { require Apache::Session::Generate::MD5; };
|
||||||
if ($@) {
|
if ($@) {
|
||||||
skip 'Apache::Session::Generate::MD5 not found', $maintests;
|
skip 'Apache::Session::Generate::MD5 not found', $maintests;
|
||||||
|
|
235
lemonldap-ng-handler/t/Time-Fake.pm
Normal file
235
lemonldap-ng-handler/t/Time-Fake.pm
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
package Time::Fake;
|
||||||
|
use Carp;
|
||||||
|
use strict;
|
||||||
|
use vars '$VERSION';
|
||||||
|
$VERSION = "0.11";
|
||||||
|
|
||||||
|
#####################
|
||||||
|
|
||||||
|
my $OFFSET = 0;
|
||||||
|
|
||||||
|
*CORE::GLOBAL::time = sub() { CORE::time() + $OFFSET };
|
||||||
|
|
||||||
|
*CORE::GLOBAL::localtime = sub(;$) {
|
||||||
|
@_ ? CORE::localtime($_[0])
|
||||||
|
: CORE::localtime(CORE::time() + $OFFSET);
|
||||||
|
};
|
||||||
|
|
||||||
|
*CORE::GLOBAL::gmtime = sub(;$) {
|
||||||
|
@_ ? CORE::gmtime($_[0])
|
||||||
|
: CORE::gmtime(CORE::time() + $OFFSET);
|
||||||
|
};
|
||||||
|
|
||||||
|
sub import {
|
||||||
|
my $pkg = shift;
|
||||||
|
$pkg->offset(shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub offset {
|
||||||
|
my $pkg = shift;
|
||||||
|
return $OFFSET if !@_;
|
||||||
|
|
||||||
|
my $old_offset = $OFFSET;
|
||||||
|
$OFFSET = _to_offset(shift);
|
||||||
|
return $old_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub reset {
|
||||||
|
shift->offset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
my %mult = (
|
||||||
|
s => 1,
|
||||||
|
m => 60,
|
||||||
|
h => 60*60,
|
||||||
|
d => 60*60*24,
|
||||||
|
M => 60*60*24*30,
|
||||||
|
y => 60*60*24*365,
|
||||||
|
);
|
||||||
|
|
||||||
|
sub _to_offset {
|
||||||
|
my $t = shift || return 0;
|
||||||
|
|
||||||
|
if ($t =~ m/^([+-]\d+)([smhdMy]?)$/) {
|
||||||
|
$t = $1 * $mult{ $2 || "s" };
|
||||||
|
|
||||||
|
} elsif ($t !~ m/\D/) {
|
||||||
|
$t = $t - CORE::time;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
croak "Invalid time offset: `$t'";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $t;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Time::Fake - Simulate different times without changing your system clock
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
Pretend we are running 1 day in the future:
|
||||||
|
|
||||||
|
use Time::Fake '+1d';
|
||||||
|
|
||||||
|
Pretend we are running 1 year in the past:
|
||||||
|
|
||||||
|
use Time::Fake '-1y';
|
||||||
|
|
||||||
|
Pretend the script started at epoch time 1234567:
|
||||||
|
|
||||||
|
use Time::Fake 1234567;
|
||||||
|
|
||||||
|
See what an existing script would do if run 20 years in the future:
|
||||||
|
|
||||||
|
% perl -MTime::Fake="+20y" test.pl
|
||||||
|
|
||||||
|
Run a section of code in a time warp:
|
||||||
|
|
||||||
|
use Time::Fake;
|
||||||
|
|
||||||
|
# do some setup
|
||||||
|
|
||||||
|
Time::Fake->offset("+1y");
|
||||||
|
run_tests(); # thinks it's a year ahead
|
||||||
|
|
||||||
|
Time::Fake->reset; # back to the present
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Use this module to achieve the effect of changing your system clock, but
|
||||||
|
without actually changing your system clock. It overrides the Perl builtin
|
||||||
|
subs C<time>, C<localtime>, and C<gmtime>, causing them to return a
|
||||||
|
"faked" time of your choice. From the script's point of view, time still
|
||||||
|
flows at the normal rate, but it is just offset as if it were executing
|
||||||
|
in the past or present.
|
||||||
|
|
||||||
|
You may find this module useful in writing test scripts for code that has
|
||||||
|
time-sensitive logic.
|
||||||
|
|
||||||
|
=head1 USAGE
|
||||||
|
|
||||||
|
=head2 Using and importing:
|
||||||
|
|
||||||
|
use Time::Fake $t;
|
||||||
|
|
||||||
|
Is equivalent to:
|
||||||
|
|
||||||
|
use Time::Fake;
|
||||||
|
Time::Fake->offset($t);
|
||||||
|
|
||||||
|
See below for arguments to C<offset>. This usage makes it easy to
|
||||||
|
fake the time for existing scripts, as in:
|
||||||
|
|
||||||
|
% perl -MTime::Fake=+1y script.pl
|
||||||
|
|
||||||
|
=head2 offset
|
||||||
|
|
||||||
|
Time::Fake->offset( [$t] );
|
||||||
|
|
||||||
|
C<$t> is either an epoch time, or a relative offset of the following
|
||||||
|
form:
|
||||||
|
|
||||||
|
+3 # 3 seconds in the future
|
||||||
|
-3s # 3 seconds in the past
|
||||||
|
+1h # 1 hour in the future
|
||||||
|
etc..
|
||||||
|
|
||||||
|
Relative offsets must begin with a plus or minus symbol. The supported
|
||||||
|
units are:
|
||||||
|
|
||||||
|
s second
|
||||||
|
m minute
|
||||||
|
h hour
|
||||||
|
d day (24 hours)
|
||||||
|
M month (30 days)
|
||||||
|
y year (365 days)
|
||||||
|
|
||||||
|
If C<$t> is an epoch time, then C<time>, C<localtime>, and C<gmtime>
|
||||||
|
will act as though the the current time (when C<offset> was called) was
|
||||||
|
actually at C<$t> epoch seconds.
|
||||||
|
Otherwise, the offset C<$t> will be added to the times returned by these
|
||||||
|
builtin subs.
|
||||||
|
|
||||||
|
When C<$t> is false, C<time>, C<localtime>, C<gmtime>
|
||||||
|
remain overridden, but their behavior resets to reflect the actual
|
||||||
|
system time.
|
||||||
|
|
||||||
|
When C<$t> is omitted, nothing is changed, but C<offset> returns the
|
||||||
|
current additive offset (in seconds). Otherwise, its return value is
|
||||||
|
the I<previous> offset.
|
||||||
|
|
||||||
|
C<offset> may be called several times. However, I<The effect of multiple
|
||||||
|
calls is NOT CUMULATIVE.> That is:
|
||||||
|
|
||||||
|
Time::Fake->offset("+1h");
|
||||||
|
Time::Fake->offset("+1h");
|
||||||
|
|
||||||
|
## same as
|
||||||
|
# Time::Fake->offset("+1h");
|
||||||
|
|
||||||
|
## NOT the same as
|
||||||
|
# Time::Fake->offset("+2h");
|
||||||
|
|
||||||
|
Each call to C<offset> completely cancels out the effect of any
|
||||||
|
previous calls. To make the effect cumulative, use the return value
|
||||||
|
of calling C<offset> with no arguments:
|
||||||
|
|
||||||
|
Time::Fake->offset("+1h");
|
||||||
|
...
|
||||||
|
Time::Fake->offset( Time::Fake->offset + 3600 ); # add another hour
|
||||||
|
|
||||||
|
=head2 reset
|
||||||
|
|
||||||
|
Time::Fake->reset;
|
||||||
|
|
||||||
|
Is the same as:
|
||||||
|
|
||||||
|
Time::Fake->offset(0);
|
||||||
|
|
||||||
|
That is, it returns all the affected builtin subs to their
|
||||||
|
default behavior -- reporing the actual system time.
|
||||||
|
|
||||||
|
=head1 KNOWN CAVEATS
|
||||||
|
|
||||||
|
Time::Fake must be loaded at C<BEGIN>-time (e.g., with a standard
|
||||||
|
C<use> statement). It must be loaded before perl I<compiles> any code
|
||||||
|
that uses C<time>, C<localtime>, or C<gmtime>. Due to inherent
|
||||||
|
limitations in overriding builtin subs, any code that was compiled
|
||||||
|
before loading Time::Fake will not be affected.
|
||||||
|
|
||||||
|
Because the system clock is not being changed, only Perl code that
|
||||||
|
uses C<time>, C<localtime>, or C<gmtime> will be fooled about the date.
|
||||||
|
In particular, the operating system is not fooled,
|
||||||
|
nor are other programs. If your Perl code modifies a file for example,
|
||||||
|
the file's modification time will reflect the B<actual> (not faked) time.
|
||||||
|
Along the same lines, if your Perl script obtains the time from somewhere
|
||||||
|
other than the affected builtins subs (e.g., C<qx/date/>), the actual
|
||||||
|
(not faked) time will be reflected.
|
||||||
|
|
||||||
|
Time::Fake doesn't affect -M, -A, -C filetest operators in the way you'd
|
||||||
|
probably want. These still report the B<actual> (not faked) script start
|
||||||
|
time minus file access time.
|
||||||
|
|
||||||
|
Time::Fake has not been tested with other modules that override the time
|
||||||
|
builtins, e.g., Time::HiRes.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
Time::Warp, which uses XS to fool more of Perl.
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
Time::Fake is written by Mike Rosulek E<lt>mike@mikero.comE<gt>. Feel
|
||||||
|
free to contact me with comments, questions, patches, or whatever.
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright (c) 2008 Mike Rosulek. All rights reserved. This module is free
|
||||||
|
software; you can redistribute it and/or modify it under the same terms as Perl
|
||||||
|
itself.
|
|
@ -43,6 +43,10 @@
|
||||||
"test1.example.com": {
|
"test1.example.com": {
|
||||||
"^/AuthStrong(?#AuthnLevel=5)": "accept",
|
"^/AuthStrong(?#AuthnLevel=5)": "accept",
|
||||||
"^/AuthWeak(?#AuthnLevel=1)": "accept",
|
"^/AuthWeak(?#AuthnLevel=1)": "accept",
|
||||||
|
"^/test-uri1": "varIsInUri($ENV{REQUEST_URI}, '/test-uri1/', $uid, 1)",
|
||||||
|
"^/test-uri2": "varIsInUri($ENV{REQUEST_URI}, '/test-uri2/', $uid)",
|
||||||
|
"^/test-restricted_uri": "varIsInUri($ENV{REQUEST_URI}, '/test-restricted_uri/', \"$uid/\", 1)",
|
||||||
|
"^/skipif": "$ENV{REQUEST_URI} =~ /zz/ ? skip : 1",
|
||||||
"^/logout": "logout_sso",
|
"^/logout": "logout_sso",
|
||||||
"^/deny": "deny",
|
"^/deny": "deny",
|
||||||
"^/user_(\\w+)/": "$uid eq $_rulematch[1]",
|
"^/user_(\\w+)/": "$uid eq $_rulematch[1]",
|
||||||
|
|
|
@ -9,6 +9,10 @@ use_ok('Lemonldap::NG::Common::PSGI::Cli::Lib');
|
||||||
our $client;
|
our $client;
|
||||||
our $count = 1;
|
our $count = 1;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
require 't/Time-Fake.pm';
|
||||||
|
}
|
||||||
|
|
||||||
no warnings 'redefine';
|
no warnings 'redefine';
|
||||||
|
|
||||||
my $module;
|
my $module;
|
||||||
|
|
|
@ -183,6 +183,7 @@ site/htdocs/static/languages/de.json
|
||||||
site/htdocs/static/languages/en.json
|
site/htdocs/static/languages/en.json
|
||||||
site/htdocs/static/languages/fr.json
|
site/htdocs/static/languages/fr.json
|
||||||
site/htdocs/static/languages/it.json
|
site/htdocs/static/languages/it.json
|
||||||
|
site/htdocs/static/languages/tr.json
|
||||||
site/htdocs/static/languages/vi.json
|
site/htdocs/static/languages/vi.json
|
||||||
site/htdocs/static/languages/zh.json
|
site/htdocs/static/languages/zh.json
|
||||||
site/htdocs/static/logos/ar.png
|
site/htdocs/static/logos/ar.png
|
||||||
|
|
|
@ -1070,6 +1070,12 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
'customPassword' => {
|
'customPassword' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
'customPlugins' => {
|
||||||
|
'type' => 'text'
|
||||||
|
},
|
||||||
|
'customPluginsParams' => {
|
||||||
|
'type' => 'keyTextContainer'
|
||||||
|
},
|
||||||
'customRegister' => {
|
'customRegister' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -1264,6 +1270,14 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'default' => 120,
|
'default' => 120,
|
||||||
'type' => 'int'
|
'type' => 'int'
|
||||||
},
|
},
|
||||||
|
'globalLogoutRule' => {
|
||||||
|
'default' => 0,
|
||||||
|
'type' => 'boolOrExpr'
|
||||||
|
},
|
||||||
|
'globalLogoutTimer' => {
|
||||||
|
'default' => 1,
|
||||||
|
'type' => 'bool'
|
||||||
|
},
|
||||||
'globalStorage' => {
|
'globalStorage' => {
|
||||||
'default' => 'Apache::Session::File',
|
'default' => 'Apache::Session::File',
|
||||||
'type' => 'PerlModule'
|
'type' => 'PerlModule'
|
||||||
|
@ -1795,7 +1809,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'managerDn' => {
|
'managerDn' => {
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'msgFail' => '__badValue__',
|
'msgFail' => '__badValue__',
|
||||||
'test' => qr/^(?:\w+=.*)?$/,
|
'test' => qr/^.*$/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
'managerPassword' => {
|
'managerPassword' => {
|
||||||
|
@ -1835,6 +1849,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
},
|
},
|
||||||
|
'notificationDefaultCond' => {
|
||||||
|
'default' => '',
|
||||||
|
'type' => 'text'
|
||||||
|
},
|
||||||
'notificationServer' => {
|
'notificationServer' => {
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
|
@ -2021,8 +2039,14 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'type' => 'subContainer'
|
'type' => 'subContainer'
|
||||||
},
|
},
|
||||||
'oidcRPMetaDataOptionsAccessTokenExpiration' => {
|
'oidcRPMetaDataOptionsAccessTokenExpiration' => {
|
||||||
'default' => 3600,
|
'type' => 'int'
|
||||||
'type' => 'int'
|
},
|
||||||
|
'oidcRPMetaDataOptionsAllowOffline' => {
|
||||||
|
'default' => 0,
|
||||||
|
'type' => 'bool'
|
||||||
|
},
|
||||||
|
'oidcRPMetaDataOptionsAuthorizationCodeExpiration' => {
|
||||||
|
'type' => 'int'
|
||||||
},
|
},
|
||||||
'oidcRPMetaDataOptionsBypassConsent' => {
|
'oidcRPMetaDataOptionsBypassConsent' => {
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
|
@ -2045,8 +2069,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
'oidcRPMetaDataOptionsIDTokenExpiration' => {
|
'oidcRPMetaDataOptionsIDTokenExpiration' => {
|
||||||
'default' => 3600,
|
'type' => 'int'
|
||||||
'type' => 'int'
|
},
|
||||||
|
'oidcRPMetaDataOptionsIDTokenForceClaims' => {
|
||||||
|
'type' => 'bool'
|
||||||
},
|
},
|
||||||
'oidcRPMetaDataOptionsIDTokenSignAlg' => {
|
'oidcRPMetaDataOptionsIDTokenSignAlg' => {
|
||||||
'default' => 'HS512',
|
'default' => 'HS512',
|
||||||
|
@ -2101,6 +2127,9 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'oidcRPMetaDataOptionsLogoutUrl' => {
|
'oidcRPMetaDataOptionsLogoutUrl' => {
|
||||||
'type' => 'url'
|
'type' => 'url'
|
||||||
},
|
},
|
||||||
|
'oidcRPMetaDataOptionsOfflineSessionExpiration' => {
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'oidcRPMetaDataOptionsPostLogoutRedirectUris' => {
|
'oidcRPMetaDataOptionsPostLogoutRedirectUris' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -2111,6 +2140,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'oidcRPMetaDataOptionsRedirectUris' => {
|
'oidcRPMetaDataOptionsRedirectUris' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
'oidcRPMetaDataOptionsRefreshToken' => {
|
||||||
|
'default' => 0,
|
||||||
|
'type' => 'bool'
|
||||||
|
},
|
||||||
'oidcRPMetaDataOptionsRequirePKCE' => {
|
'oidcRPMetaDataOptionsRequirePKCE' => {
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
|
@ -2128,6 +2161,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'default' => 600,
|
'default' => 600,
|
||||||
'type' => 'int'
|
'type' => 'int'
|
||||||
},
|
},
|
||||||
|
'oidcServiceAccessTokenExpiration' => {
|
||||||
|
'default' => 3600,
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'oidcServiceAllowAuthorizationCodeFlow' => {
|
'oidcServiceAllowAuthorizationCodeFlow' => {
|
||||||
'default' => 1,
|
'default' => 1,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
|
@ -2144,6 +2181,14 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
},
|
},
|
||||||
|
'oidcServiceAuthorizationCodeExpiration' => {
|
||||||
|
'default' => 60,
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
|
'oidcServiceIDTokenExpiration' => {
|
||||||
|
'default' => 3600,
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'oidcServiceKeyIdSig' => {
|
'oidcServiceKeyIdSig' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -2198,6 +2243,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
'default' => 'userinfo',
|
'default' => 'userinfo',
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
'oidcServiceOfflineSessionExpiration' => {
|
||||||
|
'default' => 2592000,
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'oidcServicePrivateKeySig' => {
|
'oidcServicePrivateKeySig' => {
|
||||||
'type' => 'RSAPrivateKey'
|
'type' => 'RSAPrivateKey'
|
||||||
},
|
},
|
||||||
|
@ -2588,6 +2637,9 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
],
|
],
|
||||||
'type' => 'select'
|
'type' => 'select'
|
||||||
},
|
},
|
||||||
|
'refreshSessions' => {
|
||||||
|
'type' => 'bool'
|
||||||
|
},
|
||||||
'registerConfirmSubject' => {
|
'registerConfirmSubject' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
|
|
@ -450,9 +450,10 @@ sub attributes {
|
||||||
flags => 'p',
|
flags => 'p',
|
||||||
},
|
},
|
||||||
checkUserSearchAttributes => {
|
checkUserSearchAttributes => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation => 'Attributes used for retrieving sessions in user DataBase',
|
documentation =>
|
||||||
flags => 'p',
|
'Attributes used for retrieving sessions in user DataBase',
|
||||||
|
flags => 'p',
|
||||||
},
|
},
|
||||||
checkUserDisplayPersistentInfo => {
|
checkUserDisplayPersistentInfo => {
|
||||||
default => 0,
|
default => 0,
|
||||||
|
@ -466,6 +467,18 @@ sub attributes {
|
||||||
documentation => 'Display session empty values',
|
documentation => 'Display session empty values',
|
||||||
flags => 'p',
|
flags => 'p',
|
||||||
},
|
},
|
||||||
|
globalLogoutRule => {
|
||||||
|
type => 'boolOrExpr',
|
||||||
|
default => 0,
|
||||||
|
documentation => 'Global logout activation rule',
|
||||||
|
flags => 'p',
|
||||||
|
},
|
||||||
|
globalLogoutTimer => {
|
||||||
|
default => 1,
|
||||||
|
type => 'bool',
|
||||||
|
documentation => 'Global logout auto accept time',
|
||||||
|
flags => 'p',
|
||||||
|
},
|
||||||
favAppsMaxNumber => {
|
favAppsMaxNumber => {
|
||||||
default => 3,
|
default => 3,
|
||||||
type => 'int',
|
type => 'int',
|
||||||
|
@ -553,10 +566,14 @@ sub attributes {
|
||||||
documentation =>
|
documentation =>
|
||||||
'Avoid asking confirmation when an Issuer asks to renew auth',
|
'Avoid asking confirmation when an Issuer asks to renew auth',
|
||||||
},
|
},
|
||||||
|
refreshSessions => {
|
||||||
|
type => 'bool',
|
||||||
|
documentation => 'Refresh sessions plugin',
|
||||||
|
},
|
||||||
forceGlobalStorageIssuerOTT => {
|
forceGlobalStorageIssuerOTT => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Force Issuer tokens be stored into Global Storage',
|
'Force Issuer tokens to be stored into Global Storage',
|
||||||
},
|
},
|
||||||
handlerInternalCache => {
|
handlerInternalCache => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
|
@ -1110,6 +1127,11 @@ sub attributes {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation => 'Notification server activation',
|
documentation => 'Notification server activation',
|
||||||
},
|
},
|
||||||
|
notificationDefaultCond => {
|
||||||
|
type => 'text',
|
||||||
|
default => '',
|
||||||
|
documentation => 'Notification default condition',
|
||||||
|
},
|
||||||
notificationServerGET => {
|
notificationServerGET => {
|
||||||
default => 0,
|
default => 0,
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
|
@ -2042,15 +2064,15 @@ sub attributes {
|
||||||
vhostType => {
|
vhostType => {
|
||||||
type => 'select',
|
type => 'select',
|
||||||
select => [
|
select => [
|
||||||
{ k => 'AuthBasic', v => 'AuthBasic' },
|
{ k => 'AuthBasic', v => 'AuthBasic' },
|
||||||
{ k => 'CDA', v => 'CDA' },
|
{ k => 'CDA', v => 'CDA' },
|
||||||
{ k => 'DevOps', v => 'DevOps' },
|
{ k => 'DevOps', v => 'DevOps' },
|
||||||
{ k => 'DevOpsST', v => 'DevOpsST' },
|
{ k => 'DevOpsST', v => 'DevOpsST' },
|
||||||
{ k => 'Main', v => 'Main' },
|
{ k => 'Main', v => 'Main' },
|
||||||
{ k => 'OAuth2', v => 'OAuth2' },
|
{ k => 'OAuth2', v => 'OAuth2' },
|
||||||
{ k => 'SecureToken', v => 'SecureToken' },
|
{ k => 'SecureToken', v => 'SecureToken' },
|
||||||
{ k => 'ServiceToken', v => 'ServiceToken' },
|
{ k => 'ServiceToken', v => 'ServiceToken' },
|
||||||
{ k => 'ZimbraPreAuth',v => 'ZimbraPreAuth' },
|
{ k => 'ZimbraPreAuth', v => 'ZimbraPreAuth' },
|
||||||
],
|
],
|
||||||
default => 'Main',
|
default => 'Main',
|
||||||
documentation => 'Handler type',
|
documentation => 'Handler type',
|
||||||
|
@ -2925,7 +2947,7 @@ sub attributes {
|
||||||
# LDAP
|
# LDAP
|
||||||
managerDn => {
|
managerDn => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
test => qr/^(?:\w+=.*)?$/,
|
test => qr/^.*$/,
|
||||||
msgFail => '__badValue__',
|
msgFail => '__badValue__',
|
||||||
default => '',
|
default => '',
|
||||||
documentation => 'LDAP manager DN',
|
documentation => 'LDAP manager DN',
|
||||||
|
@ -3573,6 +3595,16 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
documentation => 'Custom additional parameters',
|
documentation => 'Custom additional parameters',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# Custom plugins
|
||||||
|
customPlugins => {
|
||||||
|
type => 'text',
|
||||||
|
documentation => 'Custom plugins',
|
||||||
|
},
|
||||||
|
customPluginsParams => {
|
||||||
|
type => 'keyTextContainer',
|
||||||
|
documentation => 'Custom plugins parameters',
|
||||||
|
},
|
||||||
|
|
||||||
# OpenID Connect auth params
|
# OpenID Connect auth params
|
||||||
oidcAuthnLevel => {
|
oidcAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
|
@ -3679,6 +3711,26 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation => 'OpenID Connect allow hybrid flow',
|
documentation => 'OpenID Connect allow hybrid flow',
|
||||||
},
|
},
|
||||||
|
oidcServiceAuthorizationCodeExpiration => {
|
||||||
|
type => 'int',
|
||||||
|
default => 60,
|
||||||
|
documentation => 'OpenID Connect global code TTL',
|
||||||
|
},
|
||||||
|
oidcServiceAccessTokenExpiration => {
|
||||||
|
type => 'int',
|
||||||
|
default => 3600,
|
||||||
|
documentation => 'OpenID Connect global access token TTL',
|
||||||
|
},
|
||||||
|
oidcServiceIDTokenExpiration => {
|
||||||
|
type => 'int',
|
||||||
|
default => 3600,
|
||||||
|
documentation => 'OpenID Connect global ID token TTL',
|
||||||
|
},
|
||||||
|
oidcServiceOfflineSessionExpiration => {
|
||||||
|
type => 'int',
|
||||||
|
default => 2592000,
|
||||||
|
documentation => 'OpenID Connect global offline session TTL',
|
||||||
|
},
|
||||||
oidcStorage => {
|
oidcStorage => {
|
||||||
type => 'PerlModule',
|
type => 'PerlModule',
|
||||||
documentation => 'Apache::Session module to store OIDC user data',
|
documentation => 'Apache::Session module to store OIDC user data',
|
||||||
|
@ -3779,11 +3831,12 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
],
|
],
|
||||||
default => 'HS512',
|
default => 'HS512',
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsIDTokenExpiration =>
|
oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int' },
|
||||||
{ type => 'int', default => 3600 },
|
oidcRPMetaDataOptionsIDTokenForceClaims => { type => 'bool' },
|
||||||
oidcRPMetaDataOptionsAccessTokenExpiration =>
|
oidcRPMetaDataOptionsAccessTokenExpiration => { type => 'int' },
|
||||||
{ type => 'int', default => 3600 },
|
oidcRPMetaDataOptionsAuthorizationCodeExpiration => { type => 'int' },
|
||||||
oidcRPMetaDataOptionsRedirectUris => { type => 'text', },
|
oidcRPMetaDataOptionsOfflineSessionExpiration => { type => 'int' },
|
||||||
|
oidcRPMetaDataOptionsRedirectUris => { type => 'text', },
|
||||||
oidcRPMetaDataOptionsExtraClaims =>
|
oidcRPMetaDataOptionsExtraClaims =>
|
||||||
{ type => 'keyTextContainer', default => {} },
|
{ type => 'keyTextContainer', default => {} },
|
||||||
oidcRPMetaDataOptionsBypassConsent => {
|
oidcRPMetaDataOptionsBypassConsent => {
|
||||||
|
@ -3820,6 +3873,16 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation => 'Require PKCE',
|
documentation => 'Require PKCE',
|
||||||
},
|
},
|
||||||
|
oidcRPMetaDataOptionsAllowOffline => {
|
||||||
|
type => 'bool',
|
||||||
|
default => 0,
|
||||||
|
documentation => 'Allow offline access',
|
||||||
|
},
|
||||||
|
oidcRPMetaDataOptionsRefreshToken => {
|
||||||
|
type => 'bool',
|
||||||
|
default => 0,
|
||||||
|
documentation => 'Issue refresh tokens',
|
||||||
|
},
|
||||||
oidcRPMetaDataOptionsRule => {
|
oidcRPMetaDataOptionsRule => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
test => sub { return perlExpr(@_) },
|
test => sub { return perlExpr(@_) },
|
||||||
|
|
|
@ -203,7 +203,12 @@ sub cTrees {
|
||||||
'oidcRPMetaDataOptionsUserIDAttr',
|
'oidcRPMetaDataOptionsUserIDAttr',
|
||||||
'oidcRPMetaDataOptionsIDTokenSignAlg',
|
'oidcRPMetaDataOptionsIDTokenSignAlg',
|
||||||
'oidcRPMetaDataOptionsIDTokenExpiration',
|
'oidcRPMetaDataOptionsIDTokenExpiration',
|
||||||
|
'oidcRPMetaDataOptionsIDTokenForceClaims',
|
||||||
'oidcRPMetaDataOptionsAccessTokenExpiration',
|
'oidcRPMetaDataOptionsAccessTokenExpiration',
|
||||||
|
'oidcRPMetaDataOptionsAuthorizationCodeExpiration',
|
||||||
|
'oidcRPMetaDataOptionsAllowOffline',
|
||||||
|
'oidcRPMetaDataOptionsRefreshToken',
|
||||||
|
'oidcRPMetaDataOptionsOfflineSessionExpiration',
|
||||||
'oidcRPMetaDataOptionsRedirectUris',
|
'oidcRPMetaDataOptionsRedirectUris',
|
||||||
'oidcRPMetaDataOptionsBypassConsent',
|
'oidcRPMetaDataOptionsBypassConsent',
|
||||||
{
|
{
|
||||||
|
|
|
@ -103,9 +103,10 @@ sub portalConstants {
|
||||||
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
|
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
|
||||||
PE_ISSUERMISSINGREQATTR => 94,
|
PE_ISSUERMISSINGREQATTR => 94,
|
||||||
PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED => 95,
|
PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED => 95,
|
||||||
PE_RESETCERTIFICATE_INVALID => 96,
|
PE_BADOTP => 96,
|
||||||
PE_RESETCERTIFICATE_FORMEMPTY => 97,
|
PE_RESETCERTIFICATE_FORMEMPTY => 97,
|
||||||
PE_RESETCERTIFICATE_FIRSTACCESS => 98,
|
PE_RESETCERTIFICATE_FIRSTACCESS => 98,
|
||||||
|
PE_RESETCERTIFICATE_INVALID => 99,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -628,6 +628,7 @@ sub tree {
|
||||||
help => 'notifications.html#server',
|
help => 'notifications.html#server',
|
||||||
nodes => [
|
nodes => [
|
||||||
'notificationServer',
|
'notificationServer',
|
||||||
|
'notificationDefaultCond',
|
||||||
'notificationServerSentAttributes',
|
'notificationServerSentAttributes',
|
||||||
{
|
{
|
||||||
title =>
|
title =>
|
||||||
|
@ -712,6 +713,13 @@ sub tree {
|
||||||
help => 'autosignin.html',
|
help => 'autosignin.html',
|
||||||
nodes => ['autoSigninRules'],
|
nodes => ['autoSigninRules'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title => 'globalLogout',
|
||||||
|
help => 'globallogout.html',
|
||||||
|
form => 'simpleInputContainer',
|
||||||
|
nodes =>
|
||||||
|
[ 'globalLogoutRule', 'globalLogoutTimer', ],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title => 'stateCheck',
|
title => 'stateCheck',
|
||||||
help => 'checkstate.html',
|
help => 'checkstate.html',
|
||||||
|
@ -757,11 +765,15 @@ sub tree {
|
||||||
title => 'decryptValue',
|
title => 'decryptValue',
|
||||||
help => 'decryptvalue.html',
|
help => 'decryptvalue.html',
|
||||||
form => 'simpleInputContainer',
|
form => 'simpleInputContainer',
|
||||||
nodes => [
|
nodes =>
|
||||||
'decryptValueRule',
|
[ 'decryptValueRule', 'decryptValueFunctions', ]
|
||||||
'decryptValueFunctions',
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title => 'customPluginsNode',
|
||||||
|
help => 'plugincustom.html',
|
||||||
|
nodes => [ 'customPlugins', 'customPluginsParams' ]
|
||||||
|
},
|
||||||
|
'refreshSessions',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1206,6 +1218,10 @@ sub tree {
|
||||||
'oidcServiceAllowAuthorizationCodeFlow',
|
'oidcServiceAllowAuthorizationCodeFlow',
|
||||||
'oidcServiceAllowImplicitFlow',
|
'oidcServiceAllowImplicitFlow',
|
||||||
'oidcServiceAllowHybridFlow',
|
'oidcServiceAllowHybridFlow',
|
||||||
|
'oidcServiceAuthorizationCodeExpiration',
|
||||||
|
'oidcServiceAccessTokenExpiration',
|
||||||
|
'oidcServiceIDTokenExpiration',
|
||||||
|
'oidcServiceOfflineSessionExpiration',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -453,7 +453,6 @@ sub tests {
|
||||||
|
|
||||||
# Warn if 2F dependencies seem missing
|
# Warn if 2F dependencies seem missing
|
||||||
sfaDependencies => sub {
|
sfaDependencies => sub {
|
||||||
|
|
||||||
my $ok = 0;
|
my $ok = 0;
|
||||||
foreach (qw(u totp utotp yubikey)) {
|
foreach (qw(u totp utotp yubikey)) {
|
||||||
$ok ||= $conf->{ $_ . '2fActivation' };
|
$ok ||= $conf->{ $_ . '2fActivation' };
|
||||||
|
@ -684,8 +683,24 @@ sub tests {
|
||||||
"Notifications enabled WITHOUT persistent session storage" )
|
"Notifications enabled WITHOUT persistent session storage" )
|
||||||
if ( $conf->{notification} );
|
if ( $conf->{notification} );
|
||||||
return ( 1,
|
return ( 1,
|
||||||
"BruteForceProtection plugin enabled WITHOUT persistent session storage" )
|
"BruteForceProtection plugin enabled WITHOUT persistent session storage"
|
||||||
if ( $conf->{bruteForceProtection} );
|
) if ( $conf->{bruteForceProtection} );
|
||||||
|
|
||||||
|
# Return
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
# Warn if XML dependencies seem missing
|
||||||
|
xmlDependencies => sub {
|
||||||
|
return 1 unless ( $conf->{oldNotifFormat} );
|
||||||
|
eval "use XML::LibXML";
|
||||||
|
return ( 1,
|
||||||
|
"XML::LibXML module is required to enable old format notifications"
|
||||||
|
) if ($@);
|
||||||
|
eval "use XML::LibXSLT";
|
||||||
|
return ( 1,
|
||||||
|
"XML::LibXSLT module is required to enable old format notifications"
|
||||||
|
) if ($@);
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -18,7 +18,6 @@ extends 'Lemonldap::NG::Common::Conf::AccessLib';
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
|
|
||||||
has notifAccess => ( is => 'rw' );
|
has notifAccess => ( is => 'rw' );
|
||||||
|
|
||||||
has notifFormat => ( is => 'rw' );
|
has notifFormat => ( is => 'rw' );
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
|
@ -75,7 +74,6 @@ sub addRoutes {
|
||||||
{ done => { ':notificationId' => 'deleteDoneNotification' } },
|
{ done => { ':notificationId' => 'deleteDoneNotification' } },
|
||||||
['DELETE']
|
['DELETE']
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setNotifAccess {
|
sub setNotifAccess {
|
||||||
|
@ -158,6 +156,7 @@ sub notifications {
|
||||||
my ( $notifs, $res );
|
my ( $notifs, $res );
|
||||||
|
|
||||||
$notifs = $self->notifAccess->$sub();
|
$notifs = $self->notifAccess->$sub();
|
||||||
|
my $total = ( keys %$notifs );
|
||||||
|
|
||||||
# Restrict to wanted values
|
# Restrict to wanted values
|
||||||
if (
|
if (
|
||||||
|
@ -201,6 +200,7 @@ sub notifications {
|
||||||
result => 1,
|
result => 1,
|
||||||
count => $count,
|
count => $count,
|
||||||
values => $res,
|
values => $res,
|
||||||
|
total => $total
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ sub notifications {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $self->sendJSONresponse( $req,
|
return $self->sendJSONresponse( $req,
|
||||||
{ result => 1, count => scalar(@r), values => \@r } );
|
{ result => 1, count => scalar(@r), values => \@r, total => $total } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,6 +289,7 @@ sub newNotification {
|
||||||
$self->logger->debug("Notification Date = $json->{date}");
|
$self->logger->debug("Notification Date = $json->{date}");
|
||||||
|
|
||||||
unless ( $json->{date} =~ /^\d{4}-\d{2}-\d{2}$/ ) {
|
unless ( $json->{date} =~ /^\d{4}-\d{2}-\d{2}$/ ) {
|
||||||
|
$self->logger->error("Malformed date");
|
||||||
return $self->sendError( $req, "Malformed date", 200 );
|
return $self->sendError( $req, "Malformed date", 200 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,8 +313,8 @@ sub newNotification {
|
||||||
delete $json->{xml};
|
delete $json->{xml};
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->logger->error("Notification malformed $@");
|
$self->logger->error("Malformed notification $@");
|
||||||
return $self->sendError( $req, "Notification malformed: $@", 200 );
|
return $self->sendError( $req, "Malformed notification: $@", 200 );
|
||||||
}
|
}
|
||||||
$newNotif = to_json($json);
|
$newNotif = to_json($json);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ sub sessions {
|
||||||
my $params = $req->parameters();
|
my $params = $req->parameters();
|
||||||
my $type = delete $params->{sessionType};
|
my $type = delete $params->{sessionType};
|
||||||
$type = $type eq 'global' ? 'SSO' : ucfirst($type);
|
$type = $type eq 'global' ? 'SSO' : ucfirst($type);
|
||||||
|
$type = $type eq 'Offline' ? 'OIDCI' : ucfirst($type);
|
||||||
|
|
||||||
my $res;
|
my $res;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
# LemonLDAP::NG Notifications Explorer client
|
# LemonLDAP::NG Notifications Explorer client
|
||||||
###
|
###
|
||||||
|
|
||||||
|
# Max number of notifications to display (see overScheme)
|
||||||
|
max = 25
|
||||||
|
|
||||||
scheme = [
|
scheme = [
|
||||||
(v) ->
|
(v) ->
|
||||||
"groupBy=substr(uid,1)"
|
"groupBy=substr(uid,1)"
|
||||||
|
@ -11,6 +14,19 @@ scheme = [
|
||||||
"uid=#{v}"
|
"uid=#{v}"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# When number of children nodes exceeds "max" value
|
||||||
|
# and does not return "null", a level is added. See
|
||||||
|
# "$scope.updateTree" method
|
||||||
|
overScheme =
|
||||||
|
(v,level,over) ->
|
||||||
|
# "v.length > over" avoids a loop if one user opened more than "max"
|
||||||
|
# notifications
|
||||||
|
console.log 'overScheme => level', level, 'over', over
|
||||||
|
if level == 1 and v.length > over
|
||||||
|
"uid=#{v}*&groupBy=substr(uid,#{(level+over+1)})"
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
# Session menu
|
# Session menu
|
||||||
menu =
|
menu =
|
||||||
actives: [
|
actives: [
|
||||||
|
@ -109,11 +125,12 @@ llapp.controller 'NotificationsExplorerCtrl', [ '$scope', '$translator', '$locat
|
||||||
$scope.waiting = false
|
$scope.waiting = false
|
||||||
$scope.init()
|
$scope.init()
|
||||||
|
|
||||||
|
# Open node
|
||||||
$scope.stoggle = (scope) ->
|
$scope.stoggle = (scope) ->
|
||||||
node = scope.$modelValue
|
node = scope.$modelValue
|
||||||
if node.nodes.length == 0
|
if node.nodes.length == 0
|
||||||
$scope.updateTree node.value, node.nodes, node.level, node.query
|
$scope.updateTree node.value, node.nodes, node.level, node.over, node.query, node.count
|
||||||
scope.toggle()
|
scope.toggle()
|
||||||
|
|
||||||
$scope.notifDate = (s) ->
|
$scope.notifDate = (s) ->
|
||||||
if s?
|
if s?
|
||||||
|
@ -139,20 +156,35 @@ llapp.controller 'NotificationsExplorerCtrl', [ '$scope', '$translator', '$locat
|
||||||
$scope.init()
|
$scope.init()
|
||||||
|
|
||||||
autoId = 0
|
autoId = 0
|
||||||
$scope.updateTree = (value, node, level, currentQuery) ->
|
$scope.updateTree = (value, node, level, over, currentQuery, count) ->
|
||||||
$scope.waiting = true
|
$scope.waiting = true
|
||||||
query = scheme[level] value, currentQuery
|
query = scheme[level] value, currentQuery
|
||||||
|
|
||||||
|
# If number of notifications exceeds "max", call it
|
||||||
|
if count > max
|
||||||
|
if tmp = overScheme value, level, over
|
||||||
|
over++
|
||||||
|
query = tmp
|
||||||
|
level = level - 1
|
||||||
|
else
|
||||||
|
over = 0
|
||||||
|
else
|
||||||
|
over = 0
|
||||||
|
|
||||||
|
# Launch HTTP query
|
||||||
$http.get("#{scriptname}notifications/#{$scope.type}?#{query}").then (response) ->
|
$http.get("#{scriptname}notifications/#{$scope.type}?#{query}").then (response) ->
|
||||||
data = response.data
|
data = response.data
|
||||||
if data.result
|
if data.result
|
||||||
for n in data.values
|
for n in data.values
|
||||||
autoId++
|
autoId++
|
||||||
n.id = "node#{autoId}"
|
n.id = "node#{autoId}"
|
||||||
if level <scheme.length - 1
|
if level < scheme.length - 1
|
||||||
n.nodes = []
|
n.nodes = []
|
||||||
n.level = level + 1
|
n.level = level + 1
|
||||||
n.query = query
|
n.query = query
|
||||||
|
n.over = over
|
||||||
node.push n
|
node.push n
|
||||||
|
$scope.total = data.total if value == ''
|
||||||
$scope.waiting = false
|
$scope.waiting = false
|
||||||
, (resp) ->
|
, (resp) ->
|
||||||
$scope.waiting = false
|
$scope.waiting = false
|
||||||
|
@ -246,7 +278,7 @@ llapp.controller 'NotificationsExplorerCtrl', [ '$scope', '$translator', '$locat
|
||||||
$scope.currentNotification = null
|
$scope.currentNotification = null
|
||||||
$q.all [
|
$q.all [
|
||||||
$translator.init $scope.lang
|
$translator.init $scope.lang
|
||||||
$scope.updateTree '', $scope.data, 0
|
$scope.updateTree '', $scope.data, 0, 0
|
||||||
]
|
]
|
||||||
.then ->
|
.then ->
|
||||||
$scope.waiting = false
|
$scope.waiting = false
|
||||||
|
|
|
@ -78,26 +78,26 @@ overScheme =
|
||||||
_whatToTrace: (t,v,level,over) ->
|
_whatToTrace: (t,v,level,over) ->
|
||||||
# "v.length > over" avoids a loop if one user opened more than "max"
|
# "v.length > over" avoids a loop if one user opened more than "max"
|
||||||
# sessions
|
# sessions
|
||||||
console.log 'overSchema => level', level, 'over', over
|
console.log 'overScheme => level', level, 'over', over
|
||||||
if level == 1 and v.length > over
|
if level == 1 and v.length > over
|
||||||
"#{t}=#{v}*&groupBy=substr(#{t},#{(level+over+1)})"
|
"#{t}=#{v}*&groupBy=substr(#{t},#{(level+over+1)})"
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
# Note: IPv4 only
|
# Note: IPv4 only
|
||||||
ipAddr: (t,v,level,over) ->
|
ipAddr: (t,v,level,over) ->
|
||||||
console.log 'overSchema => level', level, 'over', over
|
console.log 'overScheme => level', level, 'over', over
|
||||||
if level > 0 and level < 4 and !v.match(/^\d+\.\d/) and over < 2
|
if level > 0 and level < 4 and !v.match(/^\d+\.\d/) and over < 2
|
||||||
"#{t}=#{v}*&groupBy=net(#{t},#{16*level+4*(over+1)},#{1+level+over})"
|
"#{t}=#{v}*&groupBy=net(#{t},#{16*level+4*(over+1)},#{1+level+over})"
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
_startTime: (t,v,level,over) ->
|
_startTime: (t,v,level,over) ->
|
||||||
console.log 'overSchema => level', level, 'over', over
|
console.log 'overScheme => level', level, 'over', over
|
||||||
if level > 3
|
if level > 3
|
||||||
"#{t}=#{v}*&groupBy=substr(#{t},#{(10+level+over)})"
|
"#{t}=#{v}*&groupBy=substr(#{t},#{(10+level+over)})"
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
_session_uid: (t,v,level,over) ->
|
_session_uid: (t,v,level,over) ->
|
||||||
console.log 'overSchema => level', level, 'over', over
|
console.log 'overScheme => level', level, 'over', over
|
||||||
if level == 1 and v.length > over
|
if level == 1 and v.length > over
|
||||||
"#{t}=#{v}*&groupBy=substr(#{t},#{(level+over+1)})"
|
"#{t}=#{v}*&groupBy=substr(#{t},#{(level+over+1)})"
|
||||||
else
|
else
|
||||||
|
@ -420,7 +420,7 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
|
||||||
sessionType = 'global'
|
sessionType = 'global'
|
||||||
if n == null
|
if n == null
|
||||||
$scope.type = '_whatToTrace'
|
$scope.type = '_whatToTrace'
|
||||||
else if n[1].match /^(persistent)$/
|
else if n[1].match /^(persistent|offline)$/
|
||||||
sessionType = RegExp.$1
|
sessionType = RegExp.$1
|
||||||
$scope.type = '_session_uid'
|
$scope.type = '_session_uid'
|
||||||
else
|
else
|
||||||
|
|
|
@ -44,8 +44,12 @@
|
||||||
/* Tables */
|
/* Tables */
|
||||||
|
|
||||||
.panel .table th {
|
.panel .table th {
|
||||||
width: 10%;
|
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.th_rulesAuthnLevel {
|
||||||
|
width: 2% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Category tree */
|
/* Category tree */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
.tree-node{border-width:1px;border-style:solid;border-radius:4px;margin-bottom:8px}.tree-node-default{background:#fff}.angular-ui-tree-handle{cursor:pointer}#pleaseWait{background-color:#fff;width:100%;min-height:9.9%;height:auto;z-index:5000;position:absolute;left:0;top:0;margin-left:auto;margin-right:auto;padding:30% 20%;text-align:center;opacity:.8;filter:alpha(opacity=80)}.panel .table th{width:10%;vertical-align:middle}ul.cat-tree{list-style-type:square}p.cat-tree-category{font-weight:bold}html,body{margin:0;padding:0;height:100vh;background:radial-gradient(circle at 50% 0,#fff 0,#ddd 100%) no-repeat scroll 0 0 #ddd}header#navbar{height:9vh;margin-bottom:1vh;padding-bottom:0vh}#content{max-height:86vh;height:86vh;margin:0;padding:0;position:relative}header#navbar .navbar-brand{padding:10px 15px}header#navbar .navbar-brand img{background:#fff}textarea{width:100%}textarea#privateKey,textarea#publicKey,textarea#filetext{font-size:8pt}dl,.panel{margin-bottom:8px}.panel-body{padding:5px}.input-group-solid{border:1px solid #CCC;border-radius:4px;padding:6px 12px}.input-group>.input-group-solid:last-child{border-bottom-left-radius:0;border-top-left-radius:0}#cfgnum{position:relative}#cfgnum.label-warning:hover:after{content:attr(comment);padding:4px 8px;color:rgba(0,0,0,0.5);position:absolute;left:100%;bottom:100%;white-space:nowrap;z-index:2;border-radius:5px;background:#f0ad4e}.link{cursor:pointer}#bottom .panel{height:100%;margin-top:8px}#bottom .panel-body{height:100%}#right{display:flex;flex-direction:column}#bottom{flex:1}@media(min-width:768px){.scrollable-sm{max-height:86vh !important;overflow:auto}#right,#left{max-height:86vh !important;height:86vh}#top{overflow-x:hidden}#bottom{height:43vh;overflow:hidden}}#top,#bottom,#right,#left{position:relative}@media(max-width:767px){#right{position:absolute;top:0;z-index:1000}.lmmenu{position:static;float:left;width:100%;min-height:200px;margin-top:0;border:1px solid #ccc;box-shadow:none}#content{position:relative}}.scrollable{overflow:auto}.container{padding-bottom:15px}.hresizer{position:absolute;width:6px;top:0;bottom:0;right:0;background-color:#EEE;cursor:e-resize}.vresizer{position:absolute;height:6px;left:0;right:0;top:0;background-color:#EEE;cursor:n-resize}.angular-ui-tree-empty{min-height:auto;border:0}.old{color:#A00}.new{color:#0A0}.maxw{width:100%}.center{text-align:center}.backgrounddiv{margin-top:10px}.llcontainer{position:relative;margin-bottom:10px}.navbar-nav li{line-height:50px}
|
.tree-node{border-width:1px;border-style:solid;border-radius:4px;margin-bottom:8px}.tree-node-default{background:#fff}.angular-ui-tree-handle{cursor:pointer}#pleaseWait{background-color:#fff;width:100%;min-height:9.9%;height:auto;z-index:5000;position:absolute;left:0;top:0;margin-left:auto;margin-right:auto;padding:30% 20%;text-align:center;opacity:.8;filter:alpha(opacity=80)}.panel .table th{vertical-align:middle;width:10%}.th_rulesAuthnLevel{width:2%!important}ul.cat-tree{list-style-type:square}p.cat-tree-category{font-weight:bold}html,body{margin:0;padding:0;height:100vh;background:radial-gradient(circle at 50% 0,#fff 0,#ddd 100%) no-repeat scroll 0 0 #ddd}header#navbar{height:9vh;margin-bottom:1vh;padding-bottom:0vh}#content{max-height:86vh;height:86vh;margin:0;padding:0;position:relative}header#navbar .navbar-brand{padding:10px 15px}header#navbar .navbar-brand img{background:#fff}textarea{width:100%}textarea#privateKey,textarea#publicKey,textarea#filetext{font-size:8pt}dl,.panel{margin-bottom:8px}.panel-body{padding:5px}.input-group-solid{border:1px solid #CCC;border-radius:4px;padding:6px 12px}.input-group>.input-group-solid:last-child{border-bottom-left-radius:0;border-top-left-radius:0}#cfgnum{position:relative}#cfgnum.label-warning:hover:after{content:attr(comment);padding:4px 8px;color:rgba(0,0,0,0.5);position:absolute;left:100%;bottom:100%;white-space:nowrap;z-index:2;border-radius:5px;background:#f0ad4e}.link{cursor:pointer}#bottom .panel{height:100%;margin-top:8px}#bottom .panel-body{height:100%}#right{display:flex;flex-direction:column}#bottom{flex:1}@media(min-width:768px){.scrollable-sm{max-height:86vh!important;overflow:auto}#right,#left{max-height:86vh!important;height:86vh}#top{overflow-x:hidden}#bottom{height:43vh;overflow:hidden}}#top,#bottom,#right,#left{position:relative}@media(max-width:767px){#right{position:absolute;top:0;z-index:1000}.lmmenu{position:static;float:left;width:100%;min-height:200px;margin-top:0;border:1px solid #ccc;box-shadow:none}#content{position:relative}}.scrollable{overflow:auto}.container{padding-bottom:15px}.hresizer{position:absolute;width:6px;top:0;bottom:0;right:0;background-color:#EEE;cursor:e-resize}.vresizer{position:absolute;height:6px;left:0;right:0;top:0;background-color:#EEE;cursor:n-resize}.angular-ui-tree-empty{min-height:auto;border:0}.old{color:#A00}.new{color:#0A0}.maxw{width:100%}.center{text-align:center}.backgrounddiv{margin-top:10px}.llcontainer{position:relative;margin-bottom:10px}.navbar-nav li{line-height:50px}
|
|
@ -5,11 +5,11 @@
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="20%" trspan="comments"></th>
|
<th trspan="comments"></th>
|
||||||
<th width="30%" trspan="regexps"></th>
|
<th trspan="regexps"></th>
|
||||||
<th width="40%" trspan="rules"></th>
|
<th trspan="rules"></th>
|
||||||
<th width="7%" trspan="rulesAuthnLevel"></th>
|
<th class="th_rulesAuthnLevel" trspan="rulesAuthnLevel"></th>
|
||||||
<th />
|
<th class="th_rulesAuthnLevel" />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
<input type="number" class="form-control" ng-model="s.level"/>
|
<input type="number" class="form-control" ng-model="s.level"/>
|
||||||
</td>
|
</td>
|
||||||
<td ng-if="s.re=='default'">
|
<td ng-if="s.re=='default'">
|
||||||
<input class="form-control" placeholder="defaultLevel" readonly/>
|
<input class="form-control" placeholder="default" readonly/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span ng-if="s.re!='default'" class="link text-danger glyphicon glyphicon-minus-sign" ng-click="del(currentNode.nodes,$index)"/>
|
<span ng-if="s.re!='default'" class="link text-danger glyphicon glyphicon-minus-sign" ng-click="del(currentNode.nodes,$index)"/>
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -473,19 +473,49 @@ function templates(tpl,key) {
|
||||||
"type" : "select"
|
"type" : "select"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default" : 3600,
|
|
||||||
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenExpiration",
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenExpiration",
|
||||||
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenExpiration",
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenExpiration",
|
||||||
"title" : "oidcRPMetaDataOptionsIDTokenExpiration",
|
"title" : "oidcRPMetaDataOptionsIDTokenExpiration",
|
||||||
"type" : "int"
|
"type" : "int"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default" : 3600,
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenForceClaims",
|
||||||
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsIDTokenForceClaims",
|
||||||
|
"title" : "oidcRPMetaDataOptionsIDTokenForceClaims",
|
||||||
|
"type" : "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAccessTokenExpiration",
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAccessTokenExpiration",
|
||||||
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAccessTokenExpiration",
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAccessTokenExpiration",
|
||||||
"title" : "oidcRPMetaDataOptionsAccessTokenExpiration",
|
"title" : "oidcRPMetaDataOptionsAccessTokenExpiration",
|
||||||
"type" : "int"
|
"type" : "int"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAuthorizationCodeExpiration",
|
||||||
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAuthorizationCodeExpiration",
|
||||||
|
"title" : "oidcRPMetaDataOptionsAuthorizationCodeExpiration",
|
||||||
|
"type" : "int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default" : 0,
|
||||||
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAllowOffline",
|
||||||
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsAllowOffline",
|
||||||
|
"title" : "oidcRPMetaDataOptionsAllowOffline",
|
||||||
|
"type" : "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default" : 0,
|
||||||
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRefreshToken",
|
||||||
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRefreshToken",
|
||||||
|
"title" : "oidcRPMetaDataOptionsRefreshToken",
|
||||||
|
"type" : "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsOfflineSessionExpiration",
|
||||||
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsOfflineSessionExpiration",
|
||||||
|
"title" : "oidcRPMetaDataOptionsOfflineSessionExpiration",
|
||||||
|
"type" : "int"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRedirectUris",
|
"get" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRedirectUris",
|
||||||
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRedirectUris",
|
"id" : tpl+"s/"+key+"/"+"oidcRPMetaDataOptionsRedirectUris",
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,2 +1 @@
|
||||||
(function(){var n;n={authParams:function(o,e,s){var t,a,d,i,r;for(r=[],i=s.nodes,t=0,a=i.length;t<a;t++)d=i[t],r.push(o.getKey(d));return e.all(r).then(function(){var t,a,i,r,l,c,f,h,u,g,m,_,p,w,P,v,C,b,y,x,F,K,L;for(t=!1,_=[],P=function(n){var o;if(o=n.toLowerCase(),"openidconnect"===o&&(o="oidc"),_.push(o+"Params"),"ad"===o)return _.push("ldapParams")},b=s.nodes,a=0,l=b.length;a<l;a++)d=b[a],P(d.data);for(y=s.nodes_cond,i=0,c=y.length;i<c;i++){if(d=y[i],K=0,p=d._nodes?d._nodes:d.nodes,"Choice"===s.nodes[0].data&&"choiceParams"===d.id)if(console.log("Choice is selected"),p[1].cnodes)K++;else for(p=p[1]._nodes?p[1]._nodes:p[1].nodes,r=0,f=p.length;r<f;r++)for(m=p[r],x=m.data,w=0,h=x.length;w<h;w++)"string"==typeof(L=x[w])&&P(L);else if("Combination"===s.nodes[0].data&&"combinationParams"===d.id)if(console.log("Combination is selected"),p[1].cnodes)K++;else for(p=p[1]._nodes?p[1]._nodes:p[1].nodes,v=0,u=p.length;v<u;v++)m=p[v],P(m.data.type);if(K)return o.waiting=!0,void o.download({$modelValue:p[1]}).then(function(){return n.authParams(o,e,s)})}for(F=s.nodes_cond,C=0,g=F.length;C<g;C++)d=F[C],t||-1!==_.indexOf(d.id)?d.show=!0:d.show=!1})}},window.filterFunctions=n}).call(this);
|
(function(){var F;F={authParams:function(C,b,y){var n,o,x,e,s;for(s=[],n=0,o=(e=y.nodes).length;n<o;n++)x=e[n],s.push(C.getKey(x));return b.all(s).then(function(){var n,o,e,s,t,a,d,i,r,l,c,f,h,u,g,m,_,p,w,P,v;for(!1,l=[],h=function(n){var o;if("openidconnect"===(o=n.toLowerCase())&&(o="oidc"),l.push(o+"Params"),"ad"===o)return l.push("ldapParams")},n=0,s=(m=y.nodes).length;n<s;n++)h((x=m[n]).data);for(o=0,t=(_=y.nodes_cond).length;o<t;o++){if(P=0,c=(x=_[o])._nodes?x._nodes:x.nodes,"Choice"===y.nodes[0].data&&"choiceParams"===x.id)if(console.log("Choice is selected"),c[1].cnodes)P++;else for(e=0,a=(c=c[1]._nodes?c[1]._nodes:c[1].nodes).length;e<a;e++)for(f=0,d=(p=c[e].data).length;f<d;f++)"string"==typeof(v=p[f])&&h(v);else if("Combination"===y.nodes[0].data&&"combinationParams"===x.id)if(console.log("Combination is selected"),c[1].cnodes)P++;else for(u=0,i=(c=c[1]._nodes?c[1]._nodes:c[1].nodes).length;u<i;u++)h(c[u].data.type);if(P)return C.waiting=!0,void C.download({$modelValue:c[1]}).then(function(){return F.authParams(C,b,y)})}for(g=0,r=(w=y.nodes_cond).length;g<r;g++)x=w[g],-1===l.indexOf(x.id)?x.show=!1:x.show=!0})}},window.filterFunctions=F}).call(this);
|
||||||
//# sourceMappingURL=lemonldap-ng-manager/site/htdocs/static/js/filterFunctions.min.js.map
|
|
|
@ -1 +1 @@
|
||||||
{"version":3,"sources":["lemonldap-ng-manager/site/htdocs/static/js/filterFunctions.js"],"names":["filterFunctions","authParams","scope","$q","node","i","len","n","ref","wait","nodes","length","push","getKey","all","then","j","k","l","len1","len2","len3","len4","len5","len6","m","nToShow","nd","o","p","q","r","ref1","ref2","ref3","ref4","restart","s","tmp","toLowerCase","data","nodes_cond","_nodes","id","console","log","cnodes","type","waiting","download","$modelValue","indexOf","show","window","call","this"],"mappings":"CACA,WACE,GAAIA,EAEJA,IACEC,WAAY,SAASC,EAAOC,EAAIC,GAC9B,GAAIC,GAAGC,EAAKC,EAAGC,EAAKC,CAGpB,KAFAA,KACAD,EAAMJ,EAAKM,MACNL,EAAI,EAAGC,EAAME,EAAIG,OAAQN,EAAIC,EAAKD,IACrCE,EAAIC,EAAIH,GACRI,EAAKG,KAAKV,EAAMW,OAAON,GAEzB,OAAOJ,GAAGW,IAAIL,GAAMM,KAAK,WACvB,GAAID,GAAKE,EAAGC,EAAGC,EAAGC,EAAMC,EAAMC,EAAMC,EAAMC,EAAMC,EAAMC,EAAGC,EAASC,EAAIC,EAAGC,EAAGC,EAAGC,EAAGC,EAAMC,EAAMC,EAAMC,EAAMC,EAASC,CAenH,KAdAvB,GAAM,EACNY,KACAG,EAAI,SAASQ,GACX,GAAIC,EAMJ,IALAA,EAAMD,EAAEE,cACI,kBAARD,IACFA,EAAM,QAERZ,EAAQd,KAAK0B,EAAM,UACP,OAARA,EACF,MAAOZ,GAAQd,KAAK,eAGxBoB,EAAO5B,EAAKM,MACPM,EAAI,EAAGG,EAAOa,EAAKrB,OAAQK,EAAIG,EAAMH,IACxCT,EAAIyB,EAAKhB,GACTa,EAAEtB,EAAEiC,KAGN,KADAP,EAAO7B,EAAKqC,WACPxB,EAAI,EAAGG,EAAOa,EAAKtB,OAAQM,EAAIG,EAAMH,IAAK,CAI7C,GAHAV,EAAI0B,EAAKhB,GACTmB,EAAU,EACVT,EAAKpB,EAAEmC,OAASnC,EAAEmC,OAASnC,EAAEG,MACF,WAAvBN,EAAKM,MAAM,GAAG8B,MAA8B,iBAATjC,EAAEoC,GAEvC,GADAC,QAAQC,IAAI,sBACRlB,EAAG,GAAGmB,OACRV,QAGA,KADAT,EAAKA,EAAG,GAAGe,OAASf,EAAG,GAAGe,OAASf,EAAG,GAAGjB,MACpCQ,EAAI,EAAGG,EAAOM,EAAGhB,OAAQO,EAAIG,EAAMH,IAGtC,IAFAO,EAAIE,EAAGT,GACPgB,EAAOT,EAAEe,KACJZ,EAAI,EAAGN,EAAOY,EAAKvB,OAAQiB,EAAIN,EAAMM,IAEvB,iBADjBS,EAAIH,EAAKN,KAEPC,EAAEQ,OAKL,IAA2B,gBAAvBjC,EAAKM,MAAM,GAAG8B,MAAmC,sBAATjC,EAAEoC,GAEnD,GADAC,QAAQC,IAAI,2BACRlB,EAAG,GAAGmB,OACRV,QAGA,KADAT,EAAKA,EAAG,GAAGe,OAASf,EAAG,GAAGe,OAASf,EAAG,GAAGjB,MACpCoB,EAAI,EAAGP,EAAOI,EAAGhB,OAAQmB,EAAIP,EAAMO,IACtCL,EAAIE,EAAGG,GACPD,EAAEJ,EAAEe,KAAKO,KAIf,IAAIX,EAOF,MANAlC,GAAM8C,SAAU,MAChB9C,GAAM+C,UACJC,YAAevB,EAAG,KACjBZ,KAAK,WACN,MAAOf,GAAgBC,WAAWC,EAAOC,EAAIC,KAMnD,IADA+B,EAAO/B,EAAKqC,WACPV,EAAI,EAAGP,EAAOW,EAAKxB,OAAQoB,EAAIP,EAAMO,IACxCxB,EAAI4B,EAAKJ,GACJjB,IAAkC,IAA3BY,EAAQyB,QAAQ5C,EAAEoC,IAG5BpC,EAAE6C,MAAO,EAFT7C,EAAE6C,MAAO,MASnBC,OAAOrD,gBAAkBA,IAExBsD,KAAKC","file":"lemonldap-ng-manager/site/htdocs/static/js/filterFunctions.min.js"}
|
{"version":3,"sources":["lemonldap-ng-manager/site/htdocs/static/js/filterFunctions.js"],"names":["filterFunctions","authParams","scope","$q","node","i","len","n","ref","wait","nodes","length","push","getKey","all","then","j","k","l","len1","len2","len3","len4","len5","len6","nToShow","nd","o","p","q","r","ref1","ref2","ref3","ref4","restart","s","tmp","toLowerCase","data","nodes_cond","_nodes","id","console","log","cnodes","type","waiting","download","$modelValue","indexOf","show","window","call","this"],"mappings":"CACA,WACE,IAAIA,EAEJA,EAAkB,CAChBC,WAAY,SAASC,EAAOC,EAAIC,GAC9B,IAAIC,EAAGC,EAAKC,EAAGC,EAAKC,EAGpB,IAFAA,EAAO,GAEFJ,EAAI,EAAGC,GADZE,EAAMJ,EAAKM,OACWC,OAAQN,EAAIC,EAAKD,IACrCE,EAAIC,EAAIH,GACRI,EAAKG,KAAKV,EAAMW,OAAON,IAEzB,OAAOJ,EAAGW,IAAIL,GAAMM,KAAK,WACvB,IAASC,EAAGC,EAAGC,EAAGC,EAAMC,EAAMC,EAAMC,EAAMC,EAAMC,EAASC,EAASC,EAAIC,EAAGC,EAAGC,EAAGC,EAAGC,EAAMC,EAAMC,EAAMC,EAAMC,EAASC,EAenH,KAdM,EACNX,EAAU,GACVG,EAAI,SAASQ,GACX,IAAIC,EAMJ,GAJY,mBADZA,EAAMD,EAAEE,iBAEND,EAAM,QAERZ,EAAQb,KAAKyB,EAAM,UACP,OAARA,EACF,OAAOZ,EAAQb,KAAK,eAInBI,EAAI,EAAGG,GADZY,EAAO3B,EAAKM,OACYC,OAAQK,EAAIG,EAAMH,IAExCY,GADArB,EAAIwB,EAAKf,IACLuB,MAGN,IAAKtB,EAAI,EAAGG,GADZY,EAAO5B,EAAKoC,YACY7B,OAAQM,EAAIG,EAAMH,IAAK,CAI7C,GAFAkB,EAAU,EACVT,GAFAnB,EAAIyB,EAAKf,IAEFwB,OAASlC,EAAEkC,OAASlC,EAAEG,MACF,WAAvBN,EAAKM,MAAM,GAAG6B,MAA8B,iBAAThC,EAAEmC,GAEvC,GADAC,QAAQC,IAAI,sBACRlB,EAAG,GAAGmB,OACRV,SAGA,IAAKjB,EAAI,EAAGG,GADZK,EAAKA,EAAG,GAAGe,OAASf,EAAG,GAAGe,OAASf,EAAG,GAAGhB,OACnBC,OAAQO,EAAIG,EAAMH,IAGtC,IAAKS,EAAI,EAAGL,GADZW,EADIP,EAAGR,GACEqB,MACe5B,OAAQgB,EAAIL,EAAMK,IAEvB,iBADjBS,EAAIH,EAAKN,KAEPC,EAAEQ,QAKL,GAA2B,gBAAvBhC,EAAKM,MAAM,GAAG6B,MAAmC,sBAAThC,EAAEmC,GAEnD,GADAC,QAAQC,IAAI,2BACRlB,EAAG,GAAGmB,OACRV,SAGA,IAAKN,EAAI,EAAGN,GADZG,EAAKA,EAAG,GAAGe,OAASf,EAAG,GAAGe,OAASf,EAAG,GAAGhB,OACnBC,OAAQkB,EAAIN,EAAMM,IAEtCD,EADIF,EAAGG,GACHU,KAAKO,MAIf,GAAIX,EAOF,OANAjC,EAAM6C,SAAU,OAChB7C,EAAM8C,SAAS,CACbC,YAAevB,EAAG,KACjBX,KAAK,WACN,OAAOf,EAAgBC,WAAWC,EAAOC,EAAIC,KAMnD,IAAK0B,EAAI,EAAGN,GADZU,EAAO9B,EAAKoC,YACY7B,OAAQmB,EAAIN,EAAMM,IACxCvB,EAAI2B,EAAKJ,IAC8B,IAA3BL,EAAQyB,QAAQ3C,EAAEmC,IAC5BnC,EAAE4C,MAAO,EAET5C,EAAE4C,MAAO,MAOnBC,OAAOpD,gBAAkBA,IAExBqD,KAAKC"}
|
|
@ -1 +1 @@
|
||||||
(function(){var e;(e=angular.module("llApp",["ngAria"])).provider("$translator",function(){var e,t,n,r,a,i,o,s,l,u,c,g;if(g={},decodeURIComponent(document.cookie).match(/llnglanguage=(\w+)/))g.lang=RegExp.$1;else if(navigator){for(r=[],a=[],l=[navigator.language],navigator.languages&&(l=navigator.languages),t=0,i=l.length;t<i;t++)for(s=l[t],console.log("Navigator lang",s),n=0,o=(c=window.availableLanguages).length;n<o;n++)e=c[n],console.log(" Available lang",e),u=new RegExp("^"+e+"-?"),s.match(u)?(console.log(" Matching lang =",e),r.push(e)):e.substring(0,1)===s.substring(0,1)&&a.push(e);g.lang=r[0]?r[0]:a[0]?a[0]:"en"}else g.lang="en";return console.log("Selected lang ->",g.lang),g.deferredTr=[],g.translationFields={},g.translate=function(e){return g.translationFields[e]&&(e=g.translationFields[e]),e},g.translateField=function(e,t){return g.translate(e[t])},g.translateP=function(e){return e&&g.translationFields.portal&&(e=e.replace(/__(\w+)__/g,function(e,t){return g.translate(t)})),e},this.$get=["$q","$http",function(t,n){return g.last="",g.init=function(e){var i;return e||(e=g.lang),(i=new Date).setTime(i.getTime()+2592e6),document.cookie="llnglanguage="+e+"; expires="+i.toUTCString()+"; path=/",i=t.defer(),g.last!==e?(g.last=e,n.get(window.staticPrefix+"languages/"+e+".json").then(function(e){var t,n,r,a;for(g.translationFields=e.data,n=0,r=(a=g.deferredTr).length;n<r;n++)(t=a[n]).e[t.f](g.translationFields[t.m]);return g.deferredTr=[],i.resolve("Translation files loaded")},function(e){return i.reject("")})):i.resolve("No change"),i.promise},g}],this}),e.directive("trspan",["$translator",function(r){return{restrict:"A",replace:!1,transclude:!0,scope:{trspan:"@"},link:function(e,t,n){return r.translationFields.portal?n.trspan=r.translate(n.trspan):r.deferredTr.push({e:t,f:"text",m:n.trspan}),t.text(n.trspan)},template:""}}]),e.provider("$htmlParams",function(){return this.$get=function(){var n;return n={},{set:function(e,t){return n[e]=t},menu:function(){return n.menu},params:function(){return n.params}}},this}),e.directive("script",["$htmlParams",function(a){return{restrict:"E",terminal:!0,compile:function(e,t){var n,r;if(t.type&&(r=t.type.match(/text\/(menu|parameters)/)))try{return a.set(r[1],JSON.parse(e[0].text))}catch(e){n=e,console.log("Parsing error:",n)}}}}]),e.controller("ModalInstanceCtrl",["$scope","$uibModalInstance","elem","set","init",function(a,e,t,n,r){var i,o;return null,a.elem=t,a.set=n,a.result=r,a.staticPrefix=window.staticPrefix,i=t("currentNode"),a.translateP=t("translateP"),i&&(o=i.data,a.currentNode=i),a.ok=function(){return n("result",a.result),e.close(!0)},a.cancel=function(){return i&&(a.currentNode.data=o),e.dismiss("cancel")},a.inSelect=function(e){var t,n,r;for(t=0,n=(r=a.currentNode.select).length;t<n;t++)if(r[t].k===e)return!0;return!1}}]),e.directive("onReadFile",["$parse",function(a){return{restrict:"A",scope:!1,link:function(n,e,t){var r;return r=a(t.onReadFile),e.on("change",function(e){var t;return(t=new FileReader).onload=function(e){return n.$apply(function(){return r(n,{$fileContent:e.target.result})})},t.readAsText((e.srcElement||e.target).files[0])})}}}]),e.directive("resizer",["$document",function(i){var o,s;return s=o=null,function(e,t,r){var n,a;return t.on("mousedown",function(e){return"vertical"===r.resizer?s=$(r.resizerRight).width()+$(r.resizerLeft).width():o=$(r.resizerTop).height()+$(r.resizerBottom).height(),e.preventDefault(),i.on("mousemove",n),i.on("mouseup",a)}),n=function(e){var t,n;return"vertical"===r.resizer?(t=e.pageX,r.resizerMax&&t>r.resizerMax&&(t=parseInt(r.resizerMax)),$(r.resizerLeft).css({width:t+"px"}),$(r.resizerRight).css({width:s-t+"px"})):(n=e.pageY-$("#navbar").height(),$(r.resizerTop).css({height:n+"px"}),$(r.resizerBottom).css({height:o-n+"px"}))},a=function(){return i.unbind("mousemove",n),i.unbind("mouseup",a)}}}]),e.factory("$lmhttp",["$q","$location",function(t,e){return{responseError:function(e){return 401===e.status&&window.portal?window.location=window.portal+"?url="+window.btoa(window.location).replace(/\//,"_"):t.reject(e)}}}]),e.config(["$httpProvider",function(e){return e.interceptors.push("$lmhttp")}])}).call(this);
|
(function(){var e;(e=angular.module("llApp",["ngAria"])).provider("$translator",function(){var e,t,n,r,a,i,o,s,l,u,c,g;if(g={},decodeURIComponent(document.cookie).match(/llnglanguage=(\w+)/))g.lang=RegExp.$1;else if(navigator){for(r=[],a=[],l=[navigator.language],navigator.languages&&(l=navigator.languages),t=0,i=l.length;t<i;t++)for(s=l[t],console.log("Navigator lang",s),n=0,o=(c=window.availableLanguages).length;n<o;n++)e=c[n],console.log(" Available lang",e),u=new RegExp("^"+e+"-?"),s.match(u)?(console.log(" Matching lang =",e),r.push(e)):e.substring(0,1)===s.substring(0,1)&&a.push(e);g.lang=r[0]?r[0]:a[0]?a[0]:"en"}else g.lang="en";return console.log("Selected lang ->",g.lang),g.deferredTr=[],g.translationFields={},g.translate=function(e){return g.translationFields[e]&&(e=g.translationFields[e]),e},g.translateField=function(e,t){return g.translate(e[t])},g.translateP=function(e){return e&&g.translationFields.portal&&(e=e.replace(/__(\w+)__/g,function(e,t){return g.translate(t)})),e},this.$get=["$q","$http",function(t,n){return g.last="",g.init=function(e){var i;return e=e||g.lang,(i=new Date).setTime(i.getTime()+2592e6),document.cookie="llnglanguage="+e+"; expires="+i.toUTCString()+"; path=/",i=t.defer(),g.last!==e?(g.last=e,n.get(window.staticPrefix+"languages/"+e+".json").then(function(e){var t,n,r,a;for(g.translationFields=e.data,n=0,r=(a=g.deferredTr).length;n<r;n++)(t=a[n]).e[t.f](g.translationFields[t.m]);return g.deferredTr=[],i.resolve("Translation files loaded")},function(e){return i.reject("")})):i.resolve("No change"),i.promise},g}],this}),e.directive("trspan",["$translator",function(r){return{restrict:"A",replace:!1,transclude:!0,scope:{trspan:"@"},link:function(e,t,n){return r.translationFields.portal?n.trspan=r.translate(n.trspan):r.deferredTr.push({e:t,f:"text",m:n.trspan}),t.text(n.trspan)},template:""}}]),e.provider("$htmlParams",function(){return this.$get=function(){var n;return n={},{set:function(e,t){return n[e]=t},menu:function(){return n.menu},params:function(){return n.params}}},this}),e.directive("script",["$htmlParams",function(a){return{restrict:"E",terminal:!0,compile:function(e,t){var n,r;if(t.type&&(r=t.type.match(/text\/(menu|parameters)/)))try{return a.set(r[1],JSON.parse(e[0].text))}catch(e){n=e,console.log("Parsing error:",n)}}}}]),e.controller("ModalInstanceCtrl",["$scope","$uibModalInstance","elem","set","init",function(a,e,t,n,r){var i,o;return null,a.elem=t,a.set=n,a.result=r,a.staticPrefix=window.staticPrefix,i=t("currentNode"),a.translateP=t("translateP"),i&&(o=i.data,a.currentNode=i),a.ok=function(){return n("result",a.result),e.close(!0)},a.cancel=function(){return i&&(a.currentNode.data=o),e.dismiss("cancel")},a.inSelect=function(e){var t,n,r;for(t=0,n=(r=a.currentNode.select).length;t<n;t++)if(r[t].k===e)return!0;return!1}}]),e.directive("onReadFile",["$parse",function(a){return{restrict:"A",scope:!1,link:function(n,e,t){var r;return r=a(t.onReadFile),e.on("change",function(e){var t;return(t=new FileReader).onload=function(e){return n.$apply(function(){return r(n,{$fileContent:e.target.result})})},t.readAsText((e.srcElement||e.target).files[0])})}}}]),e.directive("resizer",["$document",function(i){var o,s;return s=o=null,function(e,t,r){var n,a;return t.on("mousedown",function(e){return"vertical"===r.resizer?s=$(r.resizerRight).width()+$(r.resizerLeft).width():o=$(r.resizerTop).height()+$(r.resizerBottom).height(),e.preventDefault(),i.on("mousemove",n),i.on("mouseup",a)}),n=function(e){var t,n;return"vertical"===r.resizer?(t=e.pageX,r.resizerMax&&t>r.resizerMax&&(t=parseInt(r.resizerMax)),$(r.resizerLeft).css({width:t+"px"}),$(r.resizerRight).css({width:s-t+"px"})):(n=e.pageY-$("#navbar").height(),$(r.resizerTop).css({height:n+"px"}),$(r.resizerBottom).css({height:o-n+"px"}))},a=function(){return i.unbind("mousemove",n),i.unbind("mouseup",a)}}}]),e.factory("$lmhttp",["$q","$location",function(t,e){return{responseError:function(e){return 401===e.status&&window.portal?window.location=window.portal+"?url="+window.btoa(window.location).replace(/\//,"_"):t.reject(e)}}}]),e.config(["$httpProvider",function(e){return e.interceptors.push("$lmhttp")}])}).call(this);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,7 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var llapp, menu, scheme;
|
var llapp, max, menu, overScheme, scheme;
|
||||||
|
|
||||||
|
max = 25;
|
||||||
|
|
||||||
scheme = [
|
scheme = [
|
||||||
function(v) {
|
function(v) {
|
||||||
|
@ -17,6 +19,15 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
overScheme = function(v, level, over) {
|
||||||
|
console.log('overScheme => level', level, 'over', over);
|
||||||
|
if (level === 1 && v.length > over) {
|
||||||
|
return "uid=" + v + "*&groupBy=substr(uid," + (level + over + 1) + ")";
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
menu = {
|
menu = {
|
||||||
actives: [
|
actives: [
|
||||||
{
|
{
|
||||||
|
@ -131,9 +142,9 @@
|
||||||
var node;
|
var node;
|
||||||
node = scope.$modelValue;
|
node = scope.$modelValue;
|
||||||
if (node.nodes.length === 0) {
|
if (node.nodes.length === 0) {
|
||||||
$scope.updateTree(node.value, node.nodes, node.level, node.query);
|
$scope.updateTree(node.value, node.nodes, node.level, node.over, node.query, node.count);
|
||||||
return scope.toggle();
|
|
||||||
}
|
}
|
||||||
|
return scope.toggle();
|
||||||
};
|
};
|
||||||
$scope.notifDate = function(s) {
|
$scope.notifDate = function(s) {
|
||||||
var d;
|
var d;
|
||||||
|
@ -164,10 +175,21 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
autoId = 0;
|
autoId = 0;
|
||||||
$scope.updateTree = function(value, node, level, currentQuery) {
|
$scope.updateTree = function(value, node, level, over, currentQuery, count) {
|
||||||
var query;
|
var query, tmp;
|
||||||
$scope.waiting = true;
|
$scope.waiting = true;
|
||||||
query = scheme[level](value, currentQuery);
|
query = scheme[level](value, currentQuery);
|
||||||
|
if (count > max) {
|
||||||
|
if (tmp = overScheme(value, level, over)) {
|
||||||
|
over++;
|
||||||
|
query = tmp;
|
||||||
|
level = level - 1;
|
||||||
|
} else {
|
||||||
|
over = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
over = 0;
|
||||||
|
}
|
||||||
return $http.get(scriptname + "notifications/" + $scope.type + "?" + query).then(function(response) {
|
return $http.get(scriptname + "notifications/" + $scope.type + "?" + query).then(function(response) {
|
||||||
var data, i, len, n, ref;
|
var data, i, len, n, ref;
|
||||||
data = response.data;
|
data = response.data;
|
||||||
|
@ -181,9 +203,13 @@
|
||||||
n.nodes = [];
|
n.nodes = [];
|
||||||
n.level = level + 1;
|
n.level = level + 1;
|
||||||
n.query = query;
|
n.query = query;
|
||||||
|
n.over = over;
|
||||||
}
|
}
|
||||||
node.push(n);
|
node.push(n);
|
||||||
}
|
}
|
||||||
|
if (value === '') {
|
||||||
|
$scope.total = data.total;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $scope.waiting = false;
|
return $scope.waiting = false;
|
||||||
}, function(resp) {
|
}, function(resp) {
|
||||||
|
@ -301,7 +327,7 @@
|
||||||
$scope.data = [];
|
$scope.data = [];
|
||||||
$scope.currentScope = null;
|
$scope.currentScope = null;
|
||||||
$scope.currentNotification = null;
|
$scope.currentNotification = null;
|
||||||
$q.all([$translator.init($scope.lang), $scope.updateTree('', $scope.data, 0)]).then(function() {
|
$q.all([$translator.init($scope.lang), $scope.updateTree('', $scope.data, 0, 0)]).then(function() {
|
||||||
return $scope.waiting = false;
|
return $scope.waiting = false;
|
||||||
}, function(resp) {
|
}, function(resp) {
|
||||||
return $scope.waiting = false;
|
return $scope.waiting = false;
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -83,7 +83,7 @@
|
||||||
|
|
||||||
overScheme = {
|
overScheme = {
|
||||||
_whatToTrace: function(t, v, level, over) {
|
_whatToTrace: function(t, v, level, over) {
|
||||||
console.log('overSchema => level', level, 'over', over);
|
console.log('overScheme => level', level, 'over', over);
|
||||||
if (level === 1 && v.length > over) {
|
if (level === 1 && v.length > over) {
|
||||||
return t + "=" + v + "*&groupBy=substr(" + t + "," + (level + over + 1) + ")";
|
return t + "=" + v + "*&groupBy=substr(" + t + "," + (level + over + 1) + ")";
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ipAddr: function(t, v, level, over) {
|
ipAddr: function(t, v, level, over) {
|
||||||
console.log('overSchema => level', level, 'over', over);
|
console.log('overScheme => level', level, 'over', over);
|
||||||
if (level > 0 && level < 4 && !v.match(/^\d+\.\d/) && over < 2) {
|
if (level > 0 && level < 4 && !v.match(/^\d+\.\d/) && over < 2) {
|
||||||
return t + "=" + v + "*&groupBy=net(" + t + "," + (16 * level + 4 * (over + 1)) + "," + (1 + level + over) + ")";
|
return t + "=" + v + "*&groupBy=net(" + t + "," + (16 * level + 4 * (over + 1)) + "," + (1 + level + over) + ")";
|
||||||
} else {
|
} else {
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_startTime: function(t, v, level, over) {
|
_startTime: function(t, v, level, over) {
|
||||||
console.log('overSchema => level', level, 'over', over);
|
console.log('overScheme => level', level, 'over', over);
|
||||||
if (level > 3) {
|
if (level > 3) {
|
||||||
return t + "=" + v + "*&groupBy=substr(" + t + "," + (10 + level + over) + ")";
|
return t + "=" + v + "*&groupBy=substr(" + t + "," + (10 + level + over) + ")";
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_session_uid: function(t, v, level, over) {
|
_session_uid: function(t, v, level, over) {
|
||||||
console.log('overSchema => level', level, 'over', over);
|
console.log('overScheme => level', level, 'over', over);
|
||||||
if (level === 1 && v.length > over) {
|
if (level === 1 && v.length > over) {
|
||||||
return t + "=" + v + "*&groupBy=substr(" + t + "," + (level + over + 1) + ")";
|
return t + "=" + v + "*&groupBy=substr(" + t + "," + (level + over + 1) + ")";
|
||||||
} else {
|
} else {
|
||||||
|
@ -511,7 +511,7 @@
|
||||||
sessionType = 'global';
|
sessionType = 'global';
|
||||||
if (n === null) {
|
if (n === null) {
|
||||||
$scope.type = '_whatToTrace';
|
$scope.type = '_whatToTrace';
|
||||||
} else if (n[1].match(/^(persistent)$/)) {
|
} else if (n[1].match(/^(persistent|offline)$/)) {
|
||||||
sessionType = RegExp.$1;
|
sessionType = RegExp.$1;
|
||||||
$scope.type = '_session_uid';
|
$scope.type = '_session_uid';
|
||||||
} else {
|
} else {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"وحدة مخصصة",
|
"customModule":"وحدة مخصصة",
|
||||||
"customParams":"أسماء الوحدات المخصصة",
|
"customParams":"أسماء الوحدات المخصصة",
|
||||||
"customPassword":"وحدة كلمة المرورالمخصصة",
|
"customPassword":"وحدة كلمة المرورالمخصصة",
|
||||||
|
"customPlugins":"Modules list",
|
||||||
|
"customPluginsNode":"Custom plugins",
|
||||||
|
"customPluginsParams":"Additional parameters",
|
||||||
"customPortalSkin":"غلاف البوابة مخصص",
|
"customPortalSkin":"غلاف البوابة مخصص",
|
||||||
"customRegister":"وحدة تسجيل مخصص",
|
"customRegister":"وحدة تسجيل مخصص",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -247,7 +250,7 @@
|
||||||
"dbiUserTable":"جدول المستخدم",
|
"dbiUserTable":"جدول المستخدم",
|
||||||
"decryptValue":"Decrypt value",
|
"decryptValue":"Decrypt value",
|
||||||
"decryptValueFunctions":"Decrypt functions",
|
"decryptValueFunctions":"Decrypt functions",
|
||||||
"decryptValueRule":"Use rule",
|
"decryptValueRule":"استخدام القاعدة",
|
||||||
"default":"الاعْتيادي",
|
"default":"الاعْتيادي",
|
||||||
"defaultRule":"القاعدة الاعتيادية ",
|
"defaultRule":"القاعدة الاعتيادية ",
|
||||||
"demoModeOn":"هذا المدير يعمل في طريقة العرض",
|
"demoModeOn":"هذا المدير يعمل في طريقة العرض",
|
||||||
|
@ -313,6 +316,9 @@
|
||||||
"forms":"إستمارات",
|
"forms":"إستمارات",
|
||||||
"friendlyName":"اسم مألوف",
|
"friendlyName":"اسم مألوف",
|
||||||
"generalParameters":"المعاييرالعامة",
|
"generalParameters":"المعاييرالعامة",
|
||||||
|
"globalLogout":"Global logout",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"قبول تلقائي للوقت",
|
||||||
"globalStorage":"أباتشي :: وحدة الجلسة",
|
"globalStorage":"أباتشي :: وحدة الجلسة",
|
||||||
"globalStorageOptions":"أباتشي :: معايير وحدة الجلسة",
|
"globalStorageOptions":"أباتشي :: معايير وحدة الجلسة",
|
||||||
"gpgAuthnLevel":"مستوى إثبات الهوية",
|
"gpgAuthnLevel":"مستوى إثبات الهوية",
|
||||||
|
@ -430,7 +436,7 @@
|
||||||
"loadFromUrl":"تحميل من أل يو أر ل",
|
"loadFromUrl":"تحميل من أل يو أر ل",
|
||||||
"localSessionStorage":"وحدة ذاكرة التخزين المؤقت",
|
"localSessionStorage":"وحدة ذاكرة التخزين المؤقت",
|
||||||
"localSessionStorageOptions":"خيارات وحدة التخزين المؤقت",
|
"localSessionStorageOptions":"خيارات وحدة التخزين المؤقت",
|
||||||
"locationRules":"قاعدة الدخول",
|
"locationRules":"Access rules",
|
||||||
"loginHistory":"سجل تسجيل الدخول",
|
"loginHistory":"سجل تسجيل الدخول",
|
||||||
"loginHistoryEnabled":"تفعيل",
|
"loginHistoryEnabled":"تفعيل",
|
||||||
"logo":"شعار",
|
"logo":"شعار",
|
||||||
|
@ -507,6 +513,8 @@
|
||||||
"notAValidPerlExpression":"عبارة بيرل ليست صحيحة",
|
"notAValidPerlExpression":"عبارة بيرل ليست صحيحة",
|
||||||
"notification":"تفعيل",
|
"notification":"تفعيل",
|
||||||
"notifications":"إشعار",
|
"notifications":"إشعار",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Default condition",
|
||||||
"notificationServer":"إشعارالخادم",
|
"notificationServer":"إشعارالخادم",
|
||||||
"notificationServerDELETE":"DELETE method",
|
"notificationServerDELETE":"DELETE method",
|
||||||
"notificationServerGET":"GET method",
|
"notificationServerGET":"GET method",
|
||||||
|
@ -533,6 +541,7 @@
|
||||||
"nullParams":"لا شيء في المعايير",
|
"nullParams":"لا شيء في المعايير",
|
||||||
"number":"رقم",
|
"number":"رقم",
|
||||||
"off":"إيقاف",
|
"off":"إيقاف",
|
||||||
|
"offlineSessions":"Offline sessions",
|
||||||
"oldValue":"قيمة قديمة",
|
"oldValue":"قيمة قديمة",
|
||||||
"on":"تنشيط",
|
"on":"تنشيط",
|
||||||
"oidcAuthnLevel":"مستوى إثبات الهوية",
|
"oidcAuthnLevel":"مستوى إثبات الهوية",
|
||||||
|
@ -544,6 +553,7 @@
|
||||||
"oidcOPMetaDataNode":" أوبين أيدي كونيكت بروفيدر",
|
"oidcOPMetaDataNode":" أوبين أيدي كونيكت بروفيدر",
|
||||||
"oidcOPMetaDataOptions":"الخيارات",
|
"oidcOPMetaDataOptions":"الخيارات",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"إثبات الهوية",
|
"oidcRPMetaDataOptionsAuthentication":"إثبات الهوية",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"توقيع",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"توقيع",
|
||||||
"oidcOPMetaDataOptionsClientID":"معرف العميل",
|
"oidcOPMetaDataOptionsClientID":"معرف العميل",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"سرالعميل",
|
"oidcOPMetaDataOptionsClientSecret":"سرالعميل",
|
||||||
|
@ -573,6 +583,7 @@
|
||||||
"oidcRPMetaDataNode":"الأطراف المعتمد لي أوبين أيدي كونيكت",
|
"oidcRPMetaDataNode":"الأطراف المعتمد لي أوبين أيدي كونيكت",
|
||||||
"oidcRPMetaDataOptions":"الخيارات",
|
"oidcRPMetaDataOptions":"الخيارات",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"انتهاء صلاحية التوكن",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"انتهاء صلاحية التوكن",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"تخطى الموافقة ",
|
"oidcRPMetaDataOptionsBypassConsent":"تخطى الموافقة ",
|
||||||
"oidcRPMetaDataOptionsClientID":"معرف العميل",
|
"oidcRPMetaDataOptionsClientID":"معرف العميل",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"سرالعميل",
|
"oidcRPMetaDataOptionsClientSecret":"سرالعميل",
|
||||||
|
@ -581,6 +592,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"شعار",
|
"oidcRPMetaDataOptionsIcon":"شعار",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":" انتهاء صلاحية تعريف التوكن",
|
"oidcRPMetaDataOptionsIDTokenExpiration":" انتهاء صلاحية تعريف التوكن",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"خوارزمية توقيع آي دي التوكن",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"خوارزمية توقيع آي دي التوكن",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Force claims to be returned in ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Offline session expiration",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Use refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"خاصّيّة المستخدم",
|
"oidcRPMetaDataOptionsUserIDAttr":"خاصّيّة المستخدم",
|
||||||
"oidcRPName":"اسم أوبين أيدي كونيكت RP",
|
"oidcRPName":"اسم أوبين أيدي كونيكت RP",
|
||||||
"oidcRPStateTimeout":"حالة مهلة الجلسة",
|
"oidcRPStateTimeout":"حالة مهلة الجلسة",
|
||||||
|
@ -600,6 +614,10 @@
|
||||||
"oidcServicePrivateKeySig":"توقيع على المفتاح الخاص",
|
"oidcServicePrivateKeySig":"توقيع على المفتاح الخاص",
|
||||||
"oidcServicePublicKeySig":"توقيع على المفتاح العمومي",
|
"oidcServicePublicKeySig":"توقيع على المفتاح العمومي",
|
||||||
"oidcServiceKeyIdSig":"توقيع على هوية المفتاح ",
|
"oidcServiceKeyIdSig":"توقيع على هوية المفتاح ",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
|
"oidcServiceAccessTokenExpiration":"انتهاء صلاحية التوكن",
|
||||||
|
"oidcServiceIDTokenExpiration":" انتهاء صلاحية تعريف التوكن",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Offline session expiration",
|
||||||
"oidcStorage":"اسم وحدة الجلسات",
|
"oidcStorage":"اسم وحدة الجلسات",
|
||||||
"oidcStorageOptions":"خيارات وحدة الجلسات",
|
"oidcStorageOptions":"خيارات وحدة الجلسات",
|
||||||
"oidcOPMetaDataNodes":" أوبين أيدي كونيكت بروفيدر",
|
"oidcOPMetaDataNodes":" أوبين أيدي كونيكت بروفيدر",
|
||||||
|
@ -620,6 +638,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"ترخيص كود التدفق",
|
"oidcServiceAllowAuthorizationCodeFlow":"ترخيص كود التدفق",
|
||||||
"oidcServiceAllowImplicitFlow":"التدفق الضمني",
|
"oidcServiceAllowImplicitFlow":"التدفق الضمني",
|
||||||
"oidcServiceAllowHybridFlow":"تدفق هجين",
|
"oidcServiceAllowHybridFlow":"تدفق هجين",
|
||||||
|
"oidcServiceAllowOffline":"Allow offline access",
|
||||||
"ok":"حسنا",
|
"ok":"حسنا",
|
||||||
"oldNotifFormat":"استخدام صيغة xml القديمة",
|
"oldNotifFormat":"استخدام صيغة xml القديمة",
|
||||||
"openIdAttr":"تسجيل الدخول في أوبين أيدي",
|
"openIdAttr":"تسجيل الدخول في أوبين أيدي",
|
||||||
|
@ -726,6 +745,7 @@
|
||||||
"redirectFormMethod":"طريقة إعادة توجيه الإستمارة",
|
"redirectFormMethod":"طريقة إعادة توجيه الإستمارة",
|
||||||
"redirection":"معالج إعادة التوجيه",
|
"redirection":"معالج إعادة التوجيه",
|
||||||
"reference":"مرجع",
|
"reference":"مرجع",
|
||||||
|
"refreshSessions":"Refresh sessions API",
|
||||||
"regexp":"التعبير النمطي",
|
"regexp":"التعبير النمطي",
|
||||||
"regexps":"التعبير النمطي",
|
"regexps":"التعبير النمطي",
|
||||||
"register":"تسجيل حساب جديد",
|
"register":"تسجيل حساب جديد",
|
||||||
|
@ -768,9 +788,9 @@
|
||||||
"returnUrl":"إرجاع اليو آر إل",
|
"returnUrl":"إرجاع اليو آر إل",
|
||||||
"rp":"Relying Party",
|
"rp":"Relying Party",
|
||||||
"rule":"القاعدة",
|
"rule":"القاعدة",
|
||||||
"ruleAuthnLevel":"Required authentication level",
|
"ruleAuthnLevel":"مستوى إثبات الهوية واجب",
|
||||||
"rules":"القواعد",
|
"rules":"القواعد",
|
||||||
"rulesAuthnLevel":"Required authentication levels",
|
"rulesAuthnLevel":"Required auth levels",
|
||||||
"Same":"نفسه",
|
"Same":"نفسه",
|
||||||
"save":"حفظ",
|
"save":"حفظ",
|
||||||
"saveReport":"احفظ التقرير",
|
"saveReport":"احفظ التقرير",
|
||||||
|
|
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"Custom module",
|
"customModule":"Custom module",
|
||||||
"customParams":"Custom module names",
|
"customParams":"Custom module names",
|
||||||
"customPassword":"Custom password module",
|
"customPassword":"Custom password module",
|
||||||
|
"customPlugins":"Modules list",
|
||||||
|
"customPluginsNode":"Custom plugins",
|
||||||
|
"customPluginsParams":"Additional parameters",
|
||||||
"customPortalSkin":"Custom portal skin",
|
"customPortalSkin":"Custom portal skin",
|
||||||
"customRegister":"Custom register module",
|
"customRegister":"Custom register module",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -312,6 +315,9 @@
|
||||||
"forms":"Forms",
|
"forms":"Forms",
|
||||||
"friendlyName":"Friendly name",
|
"friendlyName":"Friendly name",
|
||||||
"generalParameters":"General Parameters",
|
"generalParameters":"General Parameters",
|
||||||
|
"globalLogout":"Global logout",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"Auto accept time",
|
||||||
"globalStorage":"Apache::Session module",
|
"globalStorage":"Apache::Session module",
|
||||||
"globalStorageOptions":"Apache::Session module parameters",
|
"globalStorageOptions":"Apache::Session module parameters",
|
||||||
"gpgAuthnLevel":"Authentication level",
|
"gpgAuthnLevel":"Authentication level",
|
||||||
|
@ -506,6 +512,8 @@
|
||||||
"notAValidPerlExpression":"Not a valid Perl expression",
|
"notAValidPerlExpression":"Not a valid Perl expression",
|
||||||
"notification":"Activation",
|
"notification":"Activation",
|
||||||
"notifications":"Notifications",
|
"notifications":"Notifications",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Default condition",
|
||||||
"notificationServer":"Notification server",
|
"notificationServer":"Notification server",
|
||||||
"notificationServerDELETE":"DELETE method",
|
"notificationServerDELETE":"DELETE method",
|
||||||
"notificationServerGET":"GET method",
|
"notificationServerGET":"GET method",
|
||||||
|
@ -515,8 +523,8 @@
|
||||||
"serverNotification":"Server",
|
"serverNotification":"Server",
|
||||||
"notificationCreated":"Notification has been created",
|
"notificationCreated":"Notification has been created",
|
||||||
"notificationDeleted":"Notification deleted",
|
"notificationDeleted":"Notification deleted",
|
||||||
"notificationDone":"notification done",
|
"notificationDone":"Notification done",
|
||||||
"notificationsDone":"notifications done",
|
"notificationsDone":"Notifications done",
|
||||||
"notificationNotCreated":"The notification was not created",
|
"notificationNotCreated":"The notification was not created",
|
||||||
"notificationNotDeleted":"The notification was not marked as done",
|
"notificationNotDeleted":"The notification was not marked as done",
|
||||||
"notificationNotFound":"The notification was not found",
|
"notificationNotFound":"The notification was not found",
|
||||||
|
@ -532,6 +540,7 @@
|
||||||
"nullParams":"Null parameters",
|
"nullParams":"Null parameters",
|
||||||
"number":"Number",
|
"number":"Number",
|
||||||
"off":"Off",
|
"off":"Off",
|
||||||
|
"offlineSessions":"Offline sessions",
|
||||||
"oldValue":"Old value",
|
"oldValue":"Old value",
|
||||||
"on":"On",
|
"on":"On",
|
||||||
"oidcAuthnLevel":"Authentication level",
|
"oidcAuthnLevel":"Authentication level",
|
||||||
|
@ -543,6 +552,7 @@
|
||||||
"oidcOPMetaDataNode":"OpenID Connect Providers",
|
"oidcOPMetaDataNode":"OpenID Connect Providers",
|
||||||
"oidcOPMetaDataOptions":"Optionen",
|
"oidcOPMetaDataOptions":"Optionen",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"Authentication",
|
"oidcRPMetaDataOptionsAuthentication":"Authentication",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
|
||||||
"oidcOPMetaDataOptionsClientID":"Client ID",
|
"oidcOPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"Client secret",
|
"oidcOPMetaDataOptionsClientSecret":"Client secret",
|
||||||
|
@ -571,7 +581,8 @@
|
||||||
"oidcRPMetaDataExportedVars":"Exported attributes",
|
"oidcRPMetaDataExportedVars":"Exported attributes",
|
||||||
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
||||||
"oidcRPMetaDataOptions":"Options",
|
"oidcRPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access token expiration",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
|
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
|
||||||
"oidcRPMetaDataOptionsClientID":"Client ID",
|
"oidcRPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"Client secret",
|
"oidcRPMetaDataOptionsClientSecret":"Client secret",
|
||||||
|
@ -580,6 +591,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"Logo",
|
"oidcRPMetaDataOptionsIcon":"Logo",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
|
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Force claims to be returned in ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Offline session expiration",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Use refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
|
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
|
||||||
"oidcRPName":"OpenID Connect RP Name",
|
"oidcRPName":"OpenID Connect RP Name",
|
||||||
"oidcRPStateTimeout":"State session timeout",
|
"oidcRPStateTimeout":"State session timeout",
|
||||||
|
@ -599,6 +613,10 @@
|
||||||
"oidcServicePrivateKeySig":"Signing private key",
|
"oidcServicePrivateKeySig":"Signing private key",
|
||||||
"oidcServicePublicKeySig":"Signing public key",
|
"oidcServicePublicKeySig":"Signing public key",
|
||||||
"oidcServiceKeyIdSig":"Signing key ID",
|
"oidcServiceKeyIdSig":"Signing key ID",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
|
"oidcServiceAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcServiceIDTokenExpiration":"ID Token expiration",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Offline session expiration",
|
||||||
"oidcStorage":"Sessions module name",
|
"oidcStorage":"Sessions module name",
|
||||||
"oidcStorageOptions":"Sessions module options",
|
"oidcStorageOptions":"Sessions module options",
|
||||||
"oidcOPMetaDataNodes":"OpenID Connect Providers",
|
"oidcOPMetaDataNodes":"OpenID Connect Providers",
|
||||||
|
@ -619,6 +637,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
||||||
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
||||||
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
||||||
|
"oidcServiceAllowOffline":"Allow offline access",
|
||||||
"ok":"OK",
|
"ok":"OK",
|
||||||
"oldNotifFormat":"Use old XML format",
|
"oldNotifFormat":"Use old XML format",
|
||||||
"openIdAttr":"OpenID login",
|
"openIdAttr":"OpenID login",
|
||||||
|
@ -725,6 +744,7 @@
|
||||||
"redirectFormMethod":"Method for redirect form",
|
"redirectFormMethod":"Method for redirect form",
|
||||||
"redirection":"Handler redirections",
|
"redirection":"Handler redirections",
|
||||||
"reference":"Reference",
|
"reference":"Reference",
|
||||||
|
"refreshSessions":"Refresh sessions API",
|
||||||
"regexp":"Regular expression",
|
"regexp":"Regular expression",
|
||||||
"regexps":"Regular expressions",
|
"regexps":"Regular expressions",
|
||||||
"register":"Register new account",
|
"register":"Register new account",
|
||||||
|
@ -769,7 +789,7 @@
|
||||||
"rule":"Rule",
|
"rule":"Rule",
|
||||||
"ruleAuthnLevel":"Required authentication level",
|
"ruleAuthnLevel":"Required authentication level",
|
||||||
"rules":"Regeln",
|
"rules":"Regeln",
|
||||||
"rulesAuthnLevel":"Required authentication levels",
|
"rulesAuthnLevel":"Required auth levels",
|
||||||
"Same":"Same",
|
"Same":"Same",
|
||||||
"save":"Save",
|
"save":"Save",
|
||||||
"saveReport":"Save report",
|
"saveReport":"Save report",
|
||||||
|
|
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"Custom module",
|
"customModule":"Custom module",
|
||||||
"customParams":"Custom module names",
|
"customParams":"Custom module names",
|
||||||
"customPassword":"Custom password module",
|
"customPassword":"Custom password module",
|
||||||
|
"customPlugins":"Modules list",
|
||||||
|
"customPluginsNode":"Custom plugins",
|
||||||
|
"customPluginsParams":"Additional parameters",
|
||||||
"customPortalSkin":"Custom portal skin",
|
"customPortalSkin":"Custom portal skin",
|
||||||
"customRegister":"Custom register module",
|
"customRegister":"Custom register module",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -312,6 +315,9 @@
|
||||||
"forms":"Forms",
|
"forms":"Forms",
|
||||||
"friendlyName":"Friendly name",
|
"friendlyName":"Friendly name",
|
||||||
"generalParameters":"General Parameters",
|
"generalParameters":"General Parameters",
|
||||||
|
"globalLogout":"Global logout",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"Auto accept time",
|
||||||
"globalStorage":"Apache::Session module",
|
"globalStorage":"Apache::Session module",
|
||||||
"globalStorageOptions":"Apache::Session module parameters",
|
"globalStorageOptions":"Apache::Session module parameters",
|
||||||
"gpgAuthnLevel":"Authentication level",
|
"gpgAuthnLevel":"Authentication level",
|
||||||
|
@ -506,6 +512,8 @@
|
||||||
"notAValidPerlExpression":"Not a valid Perl expression",
|
"notAValidPerlExpression":"Not a valid Perl expression",
|
||||||
"notification":"Activation",
|
"notification":"Activation",
|
||||||
"notifications":"Notifications",
|
"notifications":"Notifications",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Default condition",
|
||||||
"notificationServer":"Notification server",
|
"notificationServer":"Notification server",
|
||||||
"notificationServerDELETE":"DELETE method",
|
"notificationServerDELETE":"DELETE method",
|
||||||
"notificationServerGET":"GET method",
|
"notificationServerGET":"GET method",
|
||||||
|
@ -515,8 +523,8 @@
|
||||||
"serverNotification":"Server",
|
"serverNotification":"Server",
|
||||||
"notificationCreated":"Notification has been created",
|
"notificationCreated":"Notification has been created",
|
||||||
"notificationDeleted":"Notification deleted",
|
"notificationDeleted":"Notification deleted",
|
||||||
"notificationDone":"notification done",
|
"notificationDone":"Notification done",
|
||||||
"notificationsDone":"notifications done",
|
"notificationsDone":"Notifications done",
|
||||||
"notificationNotCreated":"The notification was not created",
|
"notificationNotCreated":"The notification was not created",
|
||||||
"notificationNotDeleted":"The notification was not marked as done",
|
"notificationNotDeleted":"The notification was not marked as done",
|
||||||
"notificationNotFound":"The notification was not found",
|
"notificationNotFound":"The notification was not found",
|
||||||
|
@ -532,6 +540,7 @@
|
||||||
"nullParams":"Null parameters",
|
"nullParams":"Null parameters",
|
||||||
"number":"Number",
|
"number":"Number",
|
||||||
"off":"Off",
|
"off":"Off",
|
||||||
|
"offlineSessions":"Offline sessions",
|
||||||
"oldValue":"Old value",
|
"oldValue":"Old value",
|
||||||
"on":"On",
|
"on":"On",
|
||||||
"oidcAuthnLevel":"Authentication level",
|
"oidcAuthnLevel":"Authentication level",
|
||||||
|
@ -543,6 +552,7 @@
|
||||||
"oidcOPMetaDataNode":"OpenID Connect Providers",
|
"oidcOPMetaDataNode":"OpenID Connect Providers",
|
||||||
"oidcOPMetaDataOptions":"Options",
|
"oidcOPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"Authentication",
|
"oidcRPMetaDataOptionsAuthentication":"Authentication",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
|
||||||
"oidcOPMetaDataOptionsClientID":"Client ID",
|
"oidcOPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"Client secret",
|
"oidcOPMetaDataOptionsClientSecret":"Client secret",
|
||||||
|
@ -571,7 +581,8 @@
|
||||||
"oidcRPMetaDataExportedVars":"Exported attributes",
|
"oidcRPMetaDataExportedVars":"Exported attributes",
|
||||||
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
||||||
"oidcRPMetaDataOptions":"Options",
|
"oidcRPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access token expiration",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
|
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
|
||||||
"oidcRPMetaDataOptionsClientID":"Client ID",
|
"oidcRPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"Client secret",
|
"oidcRPMetaDataOptionsClientSecret":"Client secret",
|
||||||
|
@ -580,6 +591,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"Logo",
|
"oidcRPMetaDataOptionsIcon":"Logo",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
|
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Force claims to be returned in ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Offline session expiration",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Use refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
|
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
|
||||||
"oidcRPName":"OpenID Connect RP Name",
|
"oidcRPName":"OpenID Connect RP Name",
|
||||||
"oidcRPStateTimeout":"State session timeout",
|
"oidcRPStateTimeout":"State session timeout",
|
||||||
|
@ -599,6 +613,10 @@
|
||||||
"oidcServicePrivateKeySig":"Signing private key",
|
"oidcServicePrivateKeySig":"Signing private key",
|
||||||
"oidcServicePublicKeySig":"Signing public key",
|
"oidcServicePublicKeySig":"Signing public key",
|
||||||
"oidcServiceKeyIdSig":"Signing key ID",
|
"oidcServiceKeyIdSig":"Signing key ID",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
|
"oidcServiceAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcServiceIDTokenExpiration":"ID Token expiration",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Offline session expiration",
|
||||||
"oidcStorage":"Sessions module name",
|
"oidcStorage":"Sessions module name",
|
||||||
"oidcStorageOptions":"Sessions module options",
|
"oidcStorageOptions":"Sessions module options",
|
||||||
"oidcOPMetaDataNodes":"OpenID Connect Providers",
|
"oidcOPMetaDataNodes":"OpenID Connect Providers",
|
||||||
|
@ -619,6 +637,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
||||||
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
||||||
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
||||||
|
"oidcServiceAllowOffline":"Allow offline access",
|
||||||
"ok":"OK",
|
"ok":"OK",
|
||||||
"oldNotifFormat":"Use old XML format",
|
"oldNotifFormat":"Use old XML format",
|
||||||
"openIdAttr":"OpenID login",
|
"openIdAttr":"OpenID login",
|
||||||
|
@ -725,6 +744,7 @@
|
||||||
"redirectFormMethod":"Method for redirect form",
|
"redirectFormMethod":"Method for redirect form",
|
||||||
"redirection":"Handler redirections",
|
"redirection":"Handler redirections",
|
||||||
"reference":"Reference",
|
"reference":"Reference",
|
||||||
|
"refreshSessions":"Refresh sessions API",
|
||||||
"regexp":"Regular expression",
|
"regexp":"Regular expression",
|
||||||
"regexps":"Regular expressions",
|
"regexps":"Regular expressions",
|
||||||
"register":"Register new account",
|
"register":"Register new account",
|
||||||
|
@ -769,7 +789,7 @@
|
||||||
"rule":"Rule",
|
"rule":"Rule",
|
||||||
"ruleAuthnLevel":"Required authentication level",
|
"ruleAuthnLevel":"Required authentication level",
|
||||||
"rules":"Rules",
|
"rules":"Rules",
|
||||||
"rulesAuthnLevel":"Required authentication levels",
|
"rulesAuthnLevel":"Required auth levels",
|
||||||
"Same":"Same",
|
"Same":"Same",
|
||||||
"save":"Save",
|
"save":"Save",
|
||||||
"saveReport":"Save report",
|
"saveReport":"Save report",
|
||||||
|
|
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"Module personnalisé",
|
"customModule":"Module personnalisé",
|
||||||
"customParams":"Nom des modules personnalisés",
|
"customParams":"Nom des modules personnalisés",
|
||||||
"customPassword":"Module de mots-de-passe personnalisé",
|
"customPassword":"Module de mots-de-passe personnalisé",
|
||||||
|
"customPlugins":"Liste des modules",
|
||||||
|
"customPluginsNode":"Extensions personnalisées",
|
||||||
|
"customPluginsParams":"Paramètres supplémentaires",
|
||||||
"customPortalSkin":"Style personnalisé du portail",
|
"customPortalSkin":"Style personnalisé du portail",
|
||||||
"customRegister":"Module d'enregistrement personnalisé",
|
"customRegister":"Module d'enregistrement personnalisé",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -312,6 +315,9 @@
|
||||||
"forms":"Formulaires",
|
"forms":"Formulaires",
|
||||||
"friendlyName":"Nom alternatif",
|
"friendlyName":"Nom alternatif",
|
||||||
"generalParameters":"Paramètres généraux",
|
"generalParameters":"Paramètres généraux",
|
||||||
|
"globalLogout":"Déconnexion globale",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"Délai d'acceptation automatique",
|
||||||
"globalStorage":"Module Apache::Session",
|
"globalStorage":"Module Apache::Session",
|
||||||
"globalStorageOptions":"Paramètres du module Apache::Session",
|
"globalStorageOptions":"Paramètres du module Apache::Session",
|
||||||
"gpgAuthnLevel":"Niveau d'authentification",
|
"gpgAuthnLevel":"Niveau d'authentification",
|
||||||
|
@ -506,6 +512,8 @@
|
||||||
"notAValidPerlExpression":"Pas une expression Perl valide",
|
"notAValidPerlExpression":"Pas une expression Perl valide",
|
||||||
"notification":"Activation",
|
"notification":"Activation",
|
||||||
"notifications":"Notifications",
|
"notifications":"Notifications",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Condition par défaut",
|
||||||
"notificationServer":"Serveur de notifications",
|
"notificationServer":"Serveur de notifications",
|
||||||
"notificationServerDELETE":"Méthode DELETE",
|
"notificationServerDELETE":"Méthode DELETE",
|
||||||
"notificationServerGET":"Méthode GET",
|
"notificationServerGET":"Méthode GET",
|
||||||
|
@ -515,8 +523,8 @@
|
||||||
"serverNotification":"Serveur",
|
"serverNotification":"Serveur",
|
||||||
"notificationCreated":"La notification a été créée",
|
"notificationCreated":"La notification a été créée",
|
||||||
"notificationDeleted":"La notification a été marquée comme lue",
|
"notificationDeleted":"La notification a été marquée comme lue",
|
||||||
"notificationDone":"notification validée",
|
"notificationDone":"Notification validée",
|
||||||
"notificationsDone":"notifications validées",
|
"notificationsDone":"Notifications validées",
|
||||||
"notificationNotCreated":"La notification n'a pas été créée",
|
"notificationNotCreated":"La notification n'a pas été créée",
|
||||||
"notificationNotDeleted":"La notification n'a pas été marquée comme lue",
|
"notificationNotDeleted":"La notification n'a pas été marquée comme lue",
|
||||||
"notificationNotFound":"La notification n'a pas été trouvée",
|
"notificationNotFound":"La notification n'a pas été trouvée",
|
||||||
|
@ -532,6 +540,7 @@
|
||||||
"nullParams":"Paramètres Null",
|
"nullParams":"Paramètres Null",
|
||||||
"number":"Numéro",
|
"number":"Numéro",
|
||||||
"off":"Désactivé",
|
"off":"Désactivé",
|
||||||
|
"offlineSessions":"Sessions hors ligne",
|
||||||
"oldValue":"Ancienne valeur",
|
"oldValue":"Ancienne valeur",
|
||||||
"on":"Activé",
|
"on":"Activé",
|
||||||
"oidcAuthnLevel":"Niveau d'authentification",
|
"oidcAuthnLevel":"Niveau d'authentification",
|
||||||
|
@ -543,6 +552,7 @@
|
||||||
"oidcOPMetaDataNode":"Fournisseurs OpenID Connect",
|
"oidcOPMetaDataNode":"Fournisseurs OpenID Connect",
|
||||||
"oidcOPMetaDataOptions":"Options",
|
"oidcOPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"Authentification",
|
"oidcRPMetaDataOptionsAuthentication":"Authentification",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Autoriser l'accès hors ligne",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"Vérifier la signature des jetons",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"Vérifier la signature des jetons",
|
||||||
"oidcOPMetaDataOptionsClientID":"Identifiant",
|
"oidcOPMetaDataOptionsClientID":"Identifiant",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"Mot de passe",
|
"oidcOPMetaDataOptionsClientSecret":"Mot de passe",
|
||||||
|
@ -572,6 +582,7 @@
|
||||||
"oidcRPMetaDataNode":"Clients OpenID Connect",
|
"oidcRPMetaDataNode":"Clients OpenID Connect",
|
||||||
"oidcRPMetaDataOptions":"Options",
|
"oidcRPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"Expiration des jetons d'accès",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"Expiration des jetons d'accès",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Expiration des codes d'autorisation",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"Contourner le consentement",
|
"oidcRPMetaDataOptionsBypassConsent":"Contourner le consentement",
|
||||||
"oidcRPMetaDataOptionsClientID":"Identifiant",
|
"oidcRPMetaDataOptionsClientID":"Identifiant",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"Mot de passe",
|
"oidcRPMetaDataOptionsClientSecret":"Mot de passe",
|
||||||
|
@ -580,6 +591,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"Logo",
|
"oidcRPMetaDataOptionsIcon":"Logo",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":"Expiration des jetons d'identité",
|
"oidcRPMetaDataOptionsIDTokenExpiration":"Expiration des jetons d'identité",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"Algorithme de signature des jetons d'identité",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"Algorithme de signature des jetons d'identité",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Forcer la publication des attributs dans l'ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Expiration des sessions hors-ligne",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Utiliser les refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"Attribut de l'utilisateur",
|
"oidcRPMetaDataOptionsUserIDAttr":"Attribut de l'utilisateur",
|
||||||
"oidcRPName":"Nom du client OpenID Connect",
|
"oidcRPName":"Nom du client OpenID Connect",
|
||||||
"oidcRPStateTimeout":"Durée d'une session state",
|
"oidcRPStateTimeout":"Durée d'une session state",
|
||||||
|
@ -599,6 +613,10 @@
|
||||||
"oidcServicePrivateKeySig":"Clef privée de signature",
|
"oidcServicePrivateKeySig":"Clef privée de signature",
|
||||||
"oidcServicePublicKeySig":"Clef publique de signature",
|
"oidcServicePublicKeySig":"Clef publique de signature",
|
||||||
"oidcServiceKeyIdSig":"Identifiant de clef de signature",
|
"oidcServiceKeyIdSig":"Identifiant de clef de signature",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Expiration des codes d'autorisation",
|
||||||
|
"oidcServiceAccessTokenExpiration":"Expiration des jetons d'accès",
|
||||||
|
"oidcServiceIDTokenExpiration":"Expiration des jetons d'identité",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Expiration des sessions hors-ligne",
|
||||||
"oidcStorage":"Nom du module des sessions",
|
"oidcStorage":"Nom du module des sessions",
|
||||||
"oidcStorageOptions":"Options du module des sessions",
|
"oidcStorageOptions":"Options du module des sessions",
|
||||||
"oidcOPMetaDataNodes":"Fournisseurs OpenID Connect",
|
"oidcOPMetaDataNodes":"Fournisseurs OpenID Connect",
|
||||||
|
@ -619,6 +637,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
||||||
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
||||||
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
||||||
|
"oidcServiceAllowOffline":"Autoriser l'accès hors ligne",
|
||||||
"ok":"OK",
|
"ok":"OK",
|
||||||
"oldNotifFormat":"Utiliser l'ancien format XML",
|
"oldNotifFormat":"Utiliser l'ancien format XML",
|
||||||
"openIdAttr":"Identifiant OpenID",
|
"openIdAttr":"Identifiant OpenID",
|
||||||
|
@ -725,6 +744,7 @@
|
||||||
"redirectFormMethod":"Méthode du formulaire de redirection",
|
"redirectFormMethod":"Méthode du formulaire de redirection",
|
||||||
"redirection":"Redirections du Handler",
|
"redirection":"Redirections du Handler",
|
||||||
"reference":"Référence",
|
"reference":"Référence",
|
||||||
|
"refreshSessions":"API de rafraîchissement des sessions",
|
||||||
"regexp":"Expression régulière",
|
"regexp":"Expression régulière",
|
||||||
"regexps":"Expressions régulières",
|
"regexps":"Expressions régulières",
|
||||||
"register":"Créer un nouveau compte",
|
"register":"Créer un nouveau compte",
|
||||||
|
@ -769,7 +789,7 @@
|
||||||
"rule":"Règle",
|
"rule":"Règle",
|
||||||
"ruleAuthnLevel":"Niveau d'authentication requis",
|
"ruleAuthnLevel":"Niveau d'authentication requis",
|
||||||
"rules":"Règles",
|
"rules":"Règles",
|
||||||
"rulesAuthnLevel":"Niveaux d'authentification requis",
|
"rulesAuthnLevel":"Niveaux auth requis",
|
||||||
"Same":"Identique",
|
"Same":"Identique",
|
||||||
"save":"Sauver",
|
"save":"Sauver",
|
||||||
"saveReport":"Rapport de sauvegarde",
|
"saveReport":"Rapport de sauvegarde",
|
||||||
|
|
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"Personalizza modulo",
|
"customModule":"Personalizza modulo",
|
||||||
"customParams":"Personalizza i nomi dei moduli",
|
"customParams":"Personalizza i nomi dei moduli",
|
||||||
"customPassword":"Personalizza il modulo password",
|
"customPassword":"Personalizza il modulo password",
|
||||||
|
"customPlugins":"Modules list",
|
||||||
|
"customPluginsNode":"Custom plugins",
|
||||||
|
"customPluginsParams":"Additional parameters",
|
||||||
"customPortalSkin":"Personalizza faccia del portale ",
|
"customPortalSkin":"Personalizza faccia del portale ",
|
||||||
"customRegister":"Personalizza modulo di registro",
|
"customRegister":"Personalizza modulo di registro",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -246,7 +249,7 @@
|
||||||
"dbiUserTable":"Tabella utente",
|
"dbiUserTable":"Tabella utente",
|
||||||
"decryptValue":"Decrypt value",
|
"decryptValue":"Decrypt value",
|
||||||
"decryptValueFunctions":"Decrypt functions",
|
"decryptValueFunctions":"Decrypt functions",
|
||||||
"decryptValueRule":"Use rule",
|
"decryptValueRule":"Utilizza la regola",
|
||||||
"default":"Predefinito",
|
"default":"Predefinito",
|
||||||
"defaultRule":"Regola predefinita",
|
"defaultRule":"Regola predefinita",
|
||||||
"demoModeOn":"Questo gestore viene eseguito in modalità demo",
|
"demoModeOn":"Questo gestore viene eseguito in modalità demo",
|
||||||
|
@ -312,6 +315,9 @@
|
||||||
"forms":"Moduli",
|
"forms":"Moduli",
|
||||||
"friendlyName":"Nome amichevole",
|
"friendlyName":"Nome amichevole",
|
||||||
"generalParameters":"Parametri generali",
|
"generalParameters":"Parametri generali",
|
||||||
|
"globalLogout":"Global logout",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"Auto accettazione tempo",
|
||||||
"globalStorage":"Modulo Apache::Session",
|
"globalStorage":"Modulo Apache::Session",
|
||||||
"globalStorageOptions":"Parametri di modulo Apache::Session",
|
"globalStorageOptions":"Parametri di modulo Apache::Session",
|
||||||
"gpgAuthnLevel":"Livello di autenticazione",
|
"gpgAuthnLevel":"Livello di autenticazione",
|
||||||
|
@ -429,7 +435,7 @@
|
||||||
"loadFromUrl":"Carica a partire dall'URL",
|
"loadFromUrl":"Carica a partire dall'URL",
|
||||||
"localSessionStorage":"Modulo cache",
|
"localSessionStorage":"Modulo cache",
|
||||||
"localSessionStorageOptions":"Opzioni modulo cache",
|
"localSessionStorageOptions":"Opzioni modulo cache",
|
||||||
"locationRules":"Regola di accesso",
|
"locationRules":"Regole di accesso",
|
||||||
"loginHistory":"Cronologia dei login",
|
"loginHistory":"Cronologia dei login",
|
||||||
"loginHistoryEnabled":"Attivazione",
|
"loginHistoryEnabled":"Attivazione",
|
||||||
"logo":"Logo",
|
"logo":"Logo",
|
||||||
|
@ -506,6 +512,8 @@
|
||||||
"notAValidPerlExpression":"Non una valida espressione Perl",
|
"notAValidPerlExpression":"Non una valida espressione Perl",
|
||||||
"notification":"Attivazione",
|
"notification":"Attivazione",
|
||||||
"notifications":"Notifiche",
|
"notifications":"Notifiche",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Default condition",
|
||||||
"notificationServer":"Server di notifica",
|
"notificationServer":"Server di notifica",
|
||||||
"notificationServerDELETE":"DELETE method",
|
"notificationServerDELETE":"DELETE method",
|
||||||
"notificationServerGET":"GET method",
|
"notificationServerGET":"GET method",
|
||||||
|
@ -532,6 +540,7 @@
|
||||||
"nullParams":"Parametri Null",
|
"nullParams":"Parametri Null",
|
||||||
"number":"Numero",
|
"number":"Numero",
|
||||||
"off":"Off",
|
"off":"Off",
|
||||||
|
"offlineSessions":"Offline sessions",
|
||||||
"oldValue":"Vecchio valore",
|
"oldValue":"Vecchio valore",
|
||||||
"on":"On",
|
"on":"On",
|
||||||
"oidcAuthnLevel":"Livello di autenticazione",
|
"oidcAuthnLevel":"Livello di autenticazione",
|
||||||
|
@ -543,6 +552,7 @@
|
||||||
"oidcOPMetaDataNode":"Provider di OpenID Connect",
|
"oidcOPMetaDataNode":"Provider di OpenID Connect",
|
||||||
"oidcOPMetaDataOptions":"Opzioni",
|
"oidcOPMetaDataOptions":"Opzioni",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"Autenticazione",
|
"oidcRPMetaDataOptionsAuthentication":"Autenticazione",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"Controllare la firma JWT",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"Controllare la firma JWT",
|
||||||
"oidcOPMetaDataOptionsClientID":"ID Client",
|
"oidcOPMetaDataOptionsClientID":"ID Client",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"Segreto Client",
|
"oidcOPMetaDataOptionsClientSecret":"Segreto Client",
|
||||||
|
@ -572,6 +582,7 @@
|
||||||
"oidcRPMetaDataNode":"Parti basate su OpenID Connect",
|
"oidcRPMetaDataNode":"Parti basate su OpenID Connect",
|
||||||
"oidcRPMetaDataOptions":"Opzioni",
|
"oidcRPMetaDataOptions":"Opzioni",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"Scadenza accesso token",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"Scadenza accesso token",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"Consenso di bypass",
|
"oidcRPMetaDataOptionsBypassConsent":"Consenso di bypass",
|
||||||
"oidcRPMetaDataOptionsClientID":"ID Client",
|
"oidcRPMetaDataOptionsClientID":"ID Client",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"Segreto Client",
|
"oidcRPMetaDataOptionsClientSecret":"Segreto Client",
|
||||||
|
@ -580,6 +591,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"Logo",
|
"oidcRPMetaDataOptionsIcon":"Logo",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":"Scadenza ID Token",
|
"oidcRPMetaDataOptionsIDTokenExpiration":"Scadenza ID Token",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"Algoritmo di firma di identificazione di Token",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"Algoritmo di firma di identificazione di Token",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Force claims to be returned in ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Offline session expiration",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Use refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"Attributo utente",
|
"oidcRPMetaDataOptionsUserIDAttr":"Attributo utente",
|
||||||
"oidcRPName":"Nome di OpenID Connect RP",
|
"oidcRPName":"Nome di OpenID Connect RP",
|
||||||
"oidcRPStateTimeout":"Durata della sessione stato",
|
"oidcRPStateTimeout":"Durata della sessione stato",
|
||||||
|
@ -599,6 +613,10 @@
|
||||||
"oidcServicePrivateKeySig":"Firma della chiave privata",
|
"oidcServicePrivateKeySig":"Firma della chiave privata",
|
||||||
"oidcServicePublicKeySig":"Firma della chiave pubblica",
|
"oidcServicePublicKeySig":"Firma della chiave pubblica",
|
||||||
"oidcServiceKeyIdSig":"ID del codice di accesso",
|
"oidcServiceKeyIdSig":"ID del codice di accesso",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
|
"oidcServiceAccessTokenExpiration":"Scadenza accesso token",
|
||||||
|
"oidcServiceIDTokenExpiration":"Scadenza ID Token",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Offline session expiration",
|
||||||
"oidcStorage":"Nome del modulo Sessioni",
|
"oidcStorage":"Nome del modulo Sessioni",
|
||||||
"oidcStorageOptions":"Opzioni del modulo Sessioni",
|
"oidcStorageOptions":"Opzioni del modulo Sessioni",
|
||||||
"oidcOPMetaDataNodes":"Provider di OpenID Connect",
|
"oidcOPMetaDataNodes":"Provider di OpenID Connect",
|
||||||
|
@ -619,6 +637,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"Flusso del codice di autorizzazione",
|
"oidcServiceAllowAuthorizationCodeFlow":"Flusso del codice di autorizzazione",
|
||||||
"oidcServiceAllowImplicitFlow":"Flusso implicito",
|
"oidcServiceAllowImplicitFlow":"Flusso implicito",
|
||||||
"oidcServiceAllowHybridFlow":"Flusso ibrido",
|
"oidcServiceAllowHybridFlow":"Flusso ibrido",
|
||||||
|
"oidcServiceAllowOffline":"Allow offline access",
|
||||||
"ok":"OK",
|
"ok":"OK",
|
||||||
"oldNotifFormat":"Utilizza il vecchio formato XML",
|
"oldNotifFormat":"Utilizza il vecchio formato XML",
|
||||||
"openIdAttr":"Login OpenID",
|
"openIdAttr":"Login OpenID",
|
||||||
|
@ -707,12 +726,12 @@
|
||||||
"proxyUseSoap":"Usa SOAP invece di REST",
|
"proxyUseSoap":"Usa SOAP invece di REST",
|
||||||
"publicKey":"Chiave pubblica",
|
"publicKey":"Chiave pubblica",
|
||||||
"purgeNotification":"Elimina definitivamente la notifica",
|
"purgeNotification":"Elimina definitivamente la notifica",
|
||||||
"radius2f":"Radius second factor",
|
"radius2f":"Radius secondo fattore",
|
||||||
"radius2fActivation":"Attivazione",
|
"radius2fActivation":"Attivazione",
|
||||||
"radius2fServer":"Nome host del server",
|
"radius2fServer":"Nome host del server",
|
||||||
"radius2fSecret":"Segreto condiviso",
|
"radius2fSecret":"Segreto condiviso",
|
||||||
"radius2fUsernameSessionKey":"Session key containing login",
|
"radius2fUsernameSessionKey":"Session key containing login",
|
||||||
"radius2fTimeout":"Authentication timeout",
|
"radius2fTimeout":"Timeout di autenticazione",
|
||||||
"radius2fAuthnLevel":"Livello di autenticazione",
|
"radius2fAuthnLevel":"Livello di autenticazione",
|
||||||
"radius2fLogo":"Logo",
|
"radius2fLogo":"Logo",
|
||||||
"radius2fLabel":"Label",
|
"radius2fLabel":"Label",
|
||||||
|
@ -725,6 +744,7 @@
|
||||||
"redirectFormMethod":"Metodo per il modulo di reindirizzamento",
|
"redirectFormMethod":"Metodo per il modulo di reindirizzamento",
|
||||||
"redirection":"Redirezioni del gestore",
|
"redirection":"Redirezioni del gestore",
|
||||||
"reference":"Riferimento",
|
"reference":"Riferimento",
|
||||||
|
"refreshSessions":"Refresh sessions API",
|
||||||
"regexp":"Espressione regolare",
|
"regexp":"Espressione regolare",
|
||||||
"regexps":"Espressioni regolari",
|
"regexps":"Espressioni regolari",
|
||||||
"register":"Registra nuovo account",
|
"register":"Registra nuovo account",
|
||||||
|
@ -767,9 +787,9 @@
|
||||||
"returnUrl":"URL di ritorno",
|
"returnUrl":"URL di ritorno",
|
||||||
"rp":"Parte facente affidamento",
|
"rp":"Parte facente affidamento",
|
||||||
"rule":"Regola",
|
"rule":"Regola",
|
||||||
"ruleAuthnLevel":"Required authentication level",
|
"ruleAuthnLevel":"Livello di autenticazione richiesto",
|
||||||
"rules":"Regole",
|
"rules":"Regole",
|
||||||
"rulesAuthnLevel":"Required authentication levels",
|
"rulesAuthnLevel":"Required auth levels",
|
||||||
"Same":"Stesso",
|
"Same":"Stesso",
|
||||||
"save":"Salva",
|
"save":"Salva",
|
||||||
"saveReport":"Salva report",
|
"saveReport":"Salva report",
|
||||||
|
|
1104
lemonldap-ng-manager/site/htdocs/static/languages/tr.json
Normal file
1104
lemonldap-ng-manager/site/htdocs/static/languages/tr.json
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"Mô đun tùy chỉnh",
|
"customModule":"Mô đun tùy chỉnh",
|
||||||
"customParams":"Tên mô-đun tùy chỉnh",
|
"customParams":"Tên mô-đun tùy chỉnh",
|
||||||
"customPassword":"Mô đun mật khẩu tùy chỉnh",
|
"customPassword":"Mô đun mật khẩu tùy chỉnh",
|
||||||
|
"customPlugins":"Modules list",
|
||||||
|
"customPluginsNode":"Custom plugins",
|
||||||
|
"customPluginsParams":"Additional parameters",
|
||||||
"customPortalSkin":"Tùy chỉnh giao diện cổng thông tin",
|
"customPortalSkin":"Tùy chỉnh giao diện cổng thông tin",
|
||||||
"customRegister":"Module đăng ký tùy chỉnh",
|
"customRegister":"Module đăng ký tùy chỉnh",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -312,6 +315,9 @@
|
||||||
"forms":"Biểu mẫu",
|
"forms":"Biểu mẫu",
|
||||||
"friendlyName":"Tên thân thiện",
|
"friendlyName":"Tên thân thiện",
|
||||||
"generalParameters":"Thông số chung",
|
"generalParameters":"Thông số chung",
|
||||||
|
"globalLogout":"Global logout",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"Tự động chấp nhận thời gian",
|
||||||
"globalStorage":"Mô đun Apache :: Session",
|
"globalStorage":"Mô đun Apache :: Session",
|
||||||
"globalStorageOptions":"Tham số mô đun Apache :: Session ",
|
"globalStorageOptions":"Tham số mô đun Apache :: Session ",
|
||||||
"gpgAuthnLevel":"Mức xác thực",
|
"gpgAuthnLevel":"Mức xác thực",
|
||||||
|
@ -429,7 +435,7 @@
|
||||||
"loadFromUrl":"Nạp từ URL",
|
"loadFromUrl":"Nạp từ URL",
|
||||||
"localSessionStorage":"Mô-đun bộ nhớ cache",
|
"localSessionStorage":"Mô-đun bộ nhớ cache",
|
||||||
"localSessionStorageOptions":"Tùy chọn mô-đun bộ nhớ cache",
|
"localSessionStorageOptions":"Tùy chọn mô-đun bộ nhớ cache",
|
||||||
"locationRules":"Quy tắc truy cập",
|
"locationRules":"Access rules",
|
||||||
"loginHistory":"Lịch sử đăng nhập",
|
"loginHistory":"Lịch sử đăng nhập",
|
||||||
"loginHistoryEnabled":"Kích hoạt",
|
"loginHistoryEnabled":"Kích hoạt",
|
||||||
"logo":"Logo",
|
"logo":"Logo",
|
||||||
|
@ -506,6 +512,8 @@
|
||||||
"notAValidPerlExpression":"Không phải là một biểu thức Perl hợp lệ",
|
"notAValidPerlExpression":"Không phải là một biểu thức Perl hợp lệ",
|
||||||
"notification":"Kích hoạt",
|
"notification":"Kích hoạt",
|
||||||
"notifications":"Thông báo",
|
"notifications":"Thông báo",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Default condition",
|
||||||
"notificationServer":"Máy chủ Thông báo",
|
"notificationServer":"Máy chủ Thông báo",
|
||||||
"notificationServerDELETE":"DELETE method",
|
"notificationServerDELETE":"DELETE method",
|
||||||
"notificationServerGET":"GET method",
|
"notificationServerGET":"GET method",
|
||||||
|
@ -515,8 +523,8 @@
|
||||||
"serverNotification":"Server",
|
"serverNotification":"Server",
|
||||||
"notificationCreated":"Thông báo đã được tạo ra",
|
"notificationCreated":"Thông báo đã được tạo ra",
|
||||||
"notificationDeleted":"Thông báo đã xoá",
|
"notificationDeleted":"Thông báo đã xoá",
|
||||||
"notificationDone":"thông báo được thực hiện",
|
"notificationDone":"Thông báo được thực hiện",
|
||||||
"notificationsDone":"thông báo đã hoàn tất",
|
"notificationsDone":"Thông báo đã hoàn tất",
|
||||||
"notificationNotCreated":"Thông báo không được tạo ra",
|
"notificationNotCreated":"Thông báo không được tạo ra",
|
||||||
"notificationNotDeleted":"Thông báo không được đánh dấu là đã hoàn tất",
|
"notificationNotDeleted":"Thông báo không được đánh dấu là đã hoàn tất",
|
||||||
"notificationNotFound":"Không tìm thấy thông báo",
|
"notificationNotFound":"Không tìm thấy thông báo",
|
||||||
|
@ -532,6 +540,7 @@
|
||||||
"nullParams":"Tham số Null",
|
"nullParams":"Tham số Null",
|
||||||
"number":"Số",
|
"number":"Số",
|
||||||
"off":"Tắt",
|
"off":"Tắt",
|
||||||
|
"offlineSessions":"Offline sessions",
|
||||||
"oldValue":"Giá trị cũ",
|
"oldValue":"Giá trị cũ",
|
||||||
"on":"Vào",
|
"on":"Vào",
|
||||||
"oidcAuthnLevel":"Mức xác thực",
|
"oidcAuthnLevel":"Mức xác thực",
|
||||||
|
@ -543,6 +552,7 @@
|
||||||
"oidcOPMetaDataNode":"Nhà cung cấp Kết nối OpenID",
|
"oidcOPMetaDataNode":"Nhà cung cấp Kết nối OpenID",
|
||||||
"oidcOPMetaDataOptions":"Tùy chọn",
|
"oidcOPMetaDataOptions":"Tùy chọn",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"Xác thực",
|
"oidcRPMetaDataOptionsAuthentication":"Xác thực",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"Kiểm tra chữ ký JWT",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"Kiểm tra chữ ký JWT",
|
||||||
"oidcOPMetaDataOptionsClientID":"Client ID",
|
"oidcOPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"Trình khách bí mật",
|
"oidcOPMetaDataOptionsClientSecret":"Trình khách bí mật",
|
||||||
|
@ -571,7 +581,8 @@
|
||||||
"oidcRPMetaDataExportedVars":"Biến đã được xuất",
|
"oidcRPMetaDataExportedVars":"Biến đã được xuất",
|
||||||
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
||||||
"oidcRPMetaDataOptions":"Tùy chọn",
|
"oidcRPMetaDataOptions":"Tùy chọn",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"Hết hạn truy cập Token",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"Bỏ qua sự đồng ý",
|
"oidcRPMetaDataOptionsBypassConsent":"Bỏ qua sự đồng ý",
|
||||||
"oidcRPMetaDataOptionsClientID":"Client ID",
|
"oidcRPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"Trình khách bí mật",
|
"oidcRPMetaDataOptionsClientSecret":"Trình khách bí mật",
|
||||||
|
@ -580,6 +591,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"Logo",
|
"oidcRPMetaDataOptionsIcon":"Logo",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token hết hạn",
|
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token hết hạn",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"Thuật toán chữ ký ID Token",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"Thuật toán chữ ký ID Token",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Force claims to be returned in ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Offline session expiration",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Use refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"thuộc tính người dùng",
|
"oidcRPMetaDataOptionsUserIDAttr":"thuộc tính người dùng",
|
||||||
"oidcRPName":"OpenID Connect RP Name",
|
"oidcRPName":"OpenID Connect RP Name",
|
||||||
"oidcRPStateTimeout":"Thời gian chờ của trạng thái phiên làm việc",
|
"oidcRPStateTimeout":"Thời gian chờ của trạng thái phiên làm việc",
|
||||||
|
@ -599,6 +613,10 @@
|
||||||
"oidcServicePrivateKeySig":"Ký khóa cá nhân",
|
"oidcServicePrivateKeySig":"Ký khóa cá nhân",
|
||||||
"oidcServicePublicKeySig":"Ký khóa công khai",
|
"oidcServicePublicKeySig":"Ký khóa công khai",
|
||||||
"oidcServiceKeyIdSig":"Khóa ID chính",
|
"oidcServiceKeyIdSig":"Khóa ID chính",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
|
"oidcServiceAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcServiceIDTokenExpiration":"ID Token expiration",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Offline session expiration",
|
||||||
"oidcStorage":"Tên mô-đun phiên",
|
"oidcStorage":"Tên mô-đun phiên",
|
||||||
"oidcStorageOptions":"Tùy chọn mô-đun phiên",
|
"oidcStorageOptions":"Tùy chọn mô-đun phiên",
|
||||||
"oidcOPMetaDataNodes":"Nhà cung cấp Kết nối OpenID",
|
"oidcOPMetaDataNodes":"Nhà cung cấp Kết nối OpenID",
|
||||||
|
@ -619,6 +637,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"Dòng mã ủy quyền",
|
"oidcServiceAllowAuthorizationCodeFlow":"Dòng mã ủy quyền",
|
||||||
"oidcServiceAllowImplicitFlow":"Dòng chảy ngầm",
|
"oidcServiceAllowImplicitFlow":"Dòng chảy ngầm",
|
||||||
"oidcServiceAllowHybridFlow":"Dòng chảy hỗn hợp",
|
"oidcServiceAllowHybridFlow":"Dòng chảy hỗn hợp",
|
||||||
|
"oidcServiceAllowOffline":"Allow offline access",
|
||||||
"ok":"OK",
|
"ok":"OK",
|
||||||
"oldNotifFormat":"Sử dụng định dạng XML cũ",
|
"oldNotifFormat":"Sử dụng định dạng XML cũ",
|
||||||
"openIdAttr":"Đăng nhập OpenID",
|
"openIdAttr":"Đăng nhập OpenID",
|
||||||
|
@ -725,6 +744,7 @@
|
||||||
"redirectFormMethod":"Phương pháp chuyển hướng mẫu",
|
"redirectFormMethod":"Phương pháp chuyển hướng mẫu",
|
||||||
"redirection":"chuyển hướng trình điều khiển",
|
"redirection":"chuyển hướng trình điều khiển",
|
||||||
"reference":"Tham khảo",
|
"reference":"Tham khảo",
|
||||||
|
"refreshSessions":"Refresh sessions API",
|
||||||
"regexp":"Biểu thức chính quy",
|
"regexp":"Biểu thức chính quy",
|
||||||
"regexps":"Biểu thức thông thường",
|
"regexps":"Biểu thức thông thường",
|
||||||
"register":"Đăng ký tài khoản mới",
|
"register":"Đăng ký tài khoản mới",
|
||||||
|
@ -769,7 +789,7 @@
|
||||||
"rule":"Quy tắc",
|
"rule":"Quy tắc",
|
||||||
"ruleAuthnLevel":"Required authentication level",
|
"ruleAuthnLevel":"Required authentication level",
|
||||||
"rules":"Quy tắc",
|
"rules":"Quy tắc",
|
||||||
"rulesAuthnLevel":"Required authentication levels",
|
"rulesAuthnLevel":"Required auth levels",
|
||||||
"Same":"Tương tự",
|
"Same":"Tương tự",
|
||||||
"save":"Lưu",
|
"save":"Lưu",
|
||||||
"saveReport":"Lưu báo cáo",
|
"saveReport":"Lưu báo cáo",
|
||||||
|
|
|
@ -219,6 +219,9 @@
|
||||||
"customModule":"定制模块",
|
"customModule":"定制模块",
|
||||||
"customParams":"定制模块名称",
|
"customParams":"定制模块名称",
|
||||||
"customPassword":"Custom password module",
|
"customPassword":"Custom password module",
|
||||||
|
"customPlugins":"Modules list",
|
||||||
|
"customPluginsNode":"Custom plugins",
|
||||||
|
"customPluginsParams":"Additional parameters",
|
||||||
"customPortalSkin":"Custom portal skin",
|
"customPortalSkin":"Custom portal skin",
|
||||||
"customRegister":"Custom register module",
|
"customRegister":"Custom register module",
|
||||||
"customToTrace":"REMOTE_CUSTOM",
|
"customToTrace":"REMOTE_CUSTOM",
|
||||||
|
@ -312,6 +315,9 @@
|
||||||
"forms":"Forms",
|
"forms":"Forms",
|
||||||
"friendlyName":"Friendly name",
|
"friendlyName":"Friendly name",
|
||||||
"generalParameters":"通用参数",
|
"generalParameters":"通用参数",
|
||||||
|
"globalLogout":"Global logout",
|
||||||
|
"globalLogoutRule":"Activation",
|
||||||
|
"globalLogoutTimer":"自动接收时间",
|
||||||
"globalStorage":"Apache::Session 模块",
|
"globalStorage":"Apache::Session 模块",
|
||||||
"globalStorageOptions":"Apache::Session module parameters",
|
"globalStorageOptions":"Apache::Session module parameters",
|
||||||
"gpgAuthnLevel":"认证等级",
|
"gpgAuthnLevel":"认证等级",
|
||||||
|
@ -506,6 +512,8 @@
|
||||||
"notAValidPerlExpression":"Not a valid Perl expression",
|
"notAValidPerlExpression":"Not a valid Perl expression",
|
||||||
"notification":"激活",
|
"notification":"激活",
|
||||||
"notifications":"Notifications",
|
"notifications":"Notifications",
|
||||||
|
"notification_s":"notification(s)",
|
||||||
|
"notificationDefaultCond":"Default condition",
|
||||||
"notificationServer":"Notification server",
|
"notificationServer":"Notification server",
|
||||||
"notificationServerDELETE":"DELETE method",
|
"notificationServerDELETE":"DELETE method",
|
||||||
"notificationServerGET":"GET method",
|
"notificationServerGET":"GET method",
|
||||||
|
@ -515,8 +523,8 @@
|
||||||
"serverNotification":"Server",
|
"serverNotification":"Server",
|
||||||
"notificationCreated":"Notification has been created",
|
"notificationCreated":"Notification has been created",
|
||||||
"notificationDeleted":"Notification deleted",
|
"notificationDeleted":"Notification deleted",
|
||||||
"notificationDone":"notification done",
|
"notificationDone":"Notification done",
|
||||||
"notificationsDone":"notifications done",
|
"notificationsDone":"Notifications done",
|
||||||
"notificationNotCreated":"The notification was not created",
|
"notificationNotCreated":"The notification was not created",
|
||||||
"notificationNotDeleted":"The notification was not marked as done",
|
"notificationNotDeleted":"The notification was not marked as done",
|
||||||
"notificationNotFound":"The notification was not found",
|
"notificationNotFound":"The notification was not found",
|
||||||
|
@ -532,6 +540,7 @@
|
||||||
"nullParams":"Null parameters",
|
"nullParams":"Null parameters",
|
||||||
"number":"Number",
|
"number":"Number",
|
||||||
"off":"Off",
|
"off":"Off",
|
||||||
|
"offlineSessions":"Offline sessions",
|
||||||
"oldValue":"Old value",
|
"oldValue":"Old value",
|
||||||
"on":"On",
|
"on":"On",
|
||||||
"oidcAuthnLevel":"认证等级",
|
"oidcAuthnLevel":"认证等级",
|
||||||
|
@ -543,6 +552,7 @@
|
||||||
"oidcOPMetaDataNode":"OpenID Connect Providers",
|
"oidcOPMetaDataNode":"OpenID Connect Providers",
|
||||||
"oidcOPMetaDataOptions":"Options",
|
"oidcOPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAuthentication":"Authentication",
|
"oidcRPMetaDataOptionsAuthentication":"Authentication",
|
||||||
|
"oidcRPMetaDataOptionsAllowOffline":"Allow offline access",
|
||||||
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
|
"oidcOPMetaDataOptionsCheckJWTSignature":"Check JWT signature",
|
||||||
"oidcOPMetaDataOptionsClientID":"Client ID",
|
"oidcOPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcOPMetaDataOptionsClientSecret":"Client secret",
|
"oidcOPMetaDataOptionsClientSecret":"Client secret",
|
||||||
|
@ -571,7 +581,8 @@
|
||||||
"oidcRPMetaDataExportedVars":"Exported attributes",
|
"oidcRPMetaDataExportedVars":"Exported attributes",
|
||||||
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
|
||||||
"oidcRPMetaDataOptions":"Options",
|
"oidcRPMetaDataOptions":"Options",
|
||||||
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access token expiration",
|
"oidcRPMetaDataOptionsAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcRPMetaDataOptionsAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
|
"oidcRPMetaDataOptionsBypassConsent":"Bypass consent",
|
||||||
"oidcRPMetaDataOptionsClientID":"Client ID",
|
"oidcRPMetaDataOptionsClientID":"Client ID",
|
||||||
"oidcRPMetaDataOptionsClientSecret":"Client secret",
|
"oidcRPMetaDataOptionsClientSecret":"Client secret",
|
||||||
|
@ -580,6 +591,9 @@
|
||||||
"oidcRPMetaDataOptionsIcon":"Logo",
|
"oidcRPMetaDataOptionsIcon":"Logo",
|
||||||
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
|
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Token expiration",
|
||||||
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
|
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token signature algorithm",
|
||||||
|
"oidcRPMetaDataOptionsIDTokenForceClaims":"Force claims to be returned in ID Token",
|
||||||
|
"oidcRPMetaDataOptionsOfflineSessionExpiration":"Offline session expiration",
|
||||||
|
"oidcRPMetaDataOptionsRefreshToken":"Use refresh tokens",
|
||||||
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
|
"oidcRPMetaDataOptionsUserIDAttr":"User attribute",
|
||||||
"oidcRPName":"OpenID Connect RP Name",
|
"oidcRPName":"OpenID Connect RP Name",
|
||||||
"oidcRPStateTimeout":"State session timeout",
|
"oidcRPStateTimeout":"State session timeout",
|
||||||
|
@ -599,6 +613,10 @@
|
||||||
"oidcServicePrivateKeySig":"Signing private key",
|
"oidcServicePrivateKeySig":"Signing private key",
|
||||||
"oidcServicePublicKeySig":"Signing public key",
|
"oidcServicePublicKeySig":"Signing public key",
|
||||||
"oidcServiceKeyIdSig":"Signing key ID",
|
"oidcServiceKeyIdSig":"Signing key ID",
|
||||||
|
"oidcServiceAuthorizationCodeExpiration":"Authorization Code expiration",
|
||||||
|
"oidcServiceAccessTokenExpiration":"Access Token expiration",
|
||||||
|
"oidcServiceIDTokenExpiration":"ID Token expiration",
|
||||||
|
"oidcServiceOfflineSessionExpiration":"Offline session expiration",
|
||||||
"oidcStorage":"Sessions module name",
|
"oidcStorage":"Sessions module name",
|
||||||
"oidcStorageOptions":"Sessions module options",
|
"oidcStorageOptions":"Sessions module options",
|
||||||
"oidcOPMetaDataNodes":"OpenID Connect Providers",
|
"oidcOPMetaDataNodes":"OpenID Connect Providers",
|
||||||
|
@ -619,6 +637,7 @@
|
||||||
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
"oidcServiceAllowAuthorizationCodeFlow":"Authorization Code Flow",
|
||||||
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
"oidcServiceAllowImplicitFlow":"Implicit Flow",
|
||||||
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
"oidcServiceAllowHybridFlow":"Hybrid Flow",
|
||||||
|
"oidcServiceAllowOffline":"Allow offline access",
|
||||||
"ok":"OK",
|
"ok":"OK",
|
||||||
"oldNotifFormat":"Use old XML format",
|
"oldNotifFormat":"Use old XML format",
|
||||||
"openIdAttr":"OpenID login",
|
"openIdAttr":"OpenID login",
|
||||||
|
@ -725,6 +744,7 @@
|
||||||
"redirectFormMethod":"Method for redirect form",
|
"redirectFormMethod":"Method for redirect form",
|
||||||
"redirection":"Handler redirections",
|
"redirection":"Handler redirections",
|
||||||
"reference":"Reference",
|
"reference":"Reference",
|
||||||
|
"refreshSessions":"Refresh sessions API",
|
||||||
"regexp":"Regular expression",
|
"regexp":"Regular expression",
|
||||||
"regexps":"Regular expressions",
|
"regexps":"Regular expressions",
|
||||||
"register":"Register new account",
|
"register":"Register new account",
|
||||||
|
@ -769,7 +789,7 @@
|
||||||
"rule":"Rule",
|
"rule":"Rule",
|
||||||
"ruleAuthnLevel":"Required authentication level",
|
"ruleAuthnLevel":"Required authentication level",
|
||||||
"rules":"Rules",
|
"rules":"Rules",
|
||||||
"rulesAuthnLevel":"Required authentication levels",
|
"rulesAuthnLevel":"Required auth levels",
|
||||||
"Same":"Same",
|
"Same":"Same",
|
||||||
"save":"Save",
|
"save":"Save",
|
||||||
"saveReport":"Save report",
|
"saveReport":"Save report",
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div ng-show="data.length!=0" class="text-center"><p class="badge">{{total}} <span trspan="notification_s"></span></p></div>
|
||||||
<div class="region region-sidebar-first">
|
<div class="region region-sidebar-first">
|
||||||
<section id="block-superfish-1" class="block block-superfish clearfix">
|
<section id="block-superfish-1" class="block block-superfish clearfix">
|
||||||
<div ui-tree data-drag-enabled="false" id="tree-root">
|
<div ui-tree data-drag-enabled="false" id="tree-root">
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a id="a-persistent" href="#!/persistent" role="row"><i class="glyphicon glyphicon-lock"></i> {{translate('persistentSessions')}}</a></li>
|
<li><a id="a-persistent" href="#!/persistent" role="row"><i class="glyphicon glyphicon-lock"></i> {{translate('persistentSessions')}}</a></li>
|
||||||
|
<li><a id="a-offline" href="#!/offline" role="row"><i class="glyphicon glyphicon-time"></i> {{translate('offlineSessions')}}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -35,7 +35,7 @@ foreach my $lang (@langs) {
|
||||||
my @l1 = sort keys %$keys;
|
my @l1 = sort keys %$keys;
|
||||||
my @l2 = sort keys %$l;
|
my @l2 = sort keys %$l;
|
||||||
ok( $#l1 == $#l2,
|
ok( $#l1 == $#l2,
|
||||||
"'$lang' and 'en' have the same count (" . @l1 . '/' . @l2 . ")" );
|
"'$lang' and 'en' have the same count (" . @l2 . '/' . @l1 . ")" );
|
||||||
|
|
||||||
my @unTr;
|
my @unTr;
|
||||||
while (@l1) {
|
while (@l1) {
|
||||||
|
|
|
@ -109,12 +109,14 @@ lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/DecryptValue.pm
|
lib/Lemonldap/NG/Portal/Plugins/DecryptValue.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/FavApps.pm
|
lib/Lemonldap/NG/Portal/Plugins/FavApps.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/ForceAuthn.pm
|
lib/Lemonldap/NG/Portal/Plugins/ForceAuthn.pm
|
||||||
|
lib/Lemonldap/NG/Portal/Plugins/GlobalLogout.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm
|
lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/History.pm
|
lib/Lemonldap/NG/Portal/Plugins/History.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/Impersonation.pm
|
lib/Lemonldap/NG/Portal/Plugins/Impersonation.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm
|
lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/Notifications.pm
|
lib/Lemonldap/NG/Portal/Plugins/Notifications.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/PublicPages.pm
|
lib/Lemonldap/NG/Portal/Plugins/PublicPages.pm
|
||||||
|
lib/Lemonldap/NG/Portal/Plugins/Refresh.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/Register.pm
|
lib/Lemonldap/NG/Portal/Plugins/Register.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm
|
lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm
|
||||||
lib/Lemonldap/NG/Portal/Plugins/SingleSession.pm
|
lib/Lemonldap/NG/Portal/Plugins/SingleSession.pm
|
||||||
|
@ -154,8 +156,10 @@ README
|
||||||
scripts/llngDeleteSession
|
scripts/llngDeleteSession
|
||||||
site/coffee/2fregistration.coffee
|
site/coffee/2fregistration.coffee
|
||||||
site/coffee/autoRenew.coffee
|
site/coffee/autoRenew.coffee
|
||||||
|
site/coffee/captcha.coffee
|
||||||
site/coffee/confirm.coffee
|
site/coffee/confirm.coffee
|
||||||
site/coffee/favapps.coffee
|
site/coffee/favapps.coffee
|
||||||
|
site/coffee/globalLogout.coffee
|
||||||
site/coffee/idpchoice.coffee
|
site/coffee/idpchoice.coffee
|
||||||
site/coffee/info.coffee
|
site/coffee/info.coffee
|
||||||
site/coffee/kerberos.coffee
|
site/coffee/kerberos.coffee
|
||||||
|
@ -285,12 +289,18 @@ site/htdocs/static/common/js/2fregistration.min.js.map
|
||||||
site/htdocs/static/common/js/autoRenew.js
|
site/htdocs/static/common/js/autoRenew.js
|
||||||
site/htdocs/static/common/js/autoRenew.min.js
|
site/htdocs/static/common/js/autoRenew.min.js
|
||||||
site/htdocs/static/common/js/autoRenew.min.js.map
|
site/htdocs/static/common/js/autoRenew.min.js.map
|
||||||
|
site/htdocs/static/common/js/captcha.js
|
||||||
|
site/htdocs/static/common/js/captcha.min.js
|
||||||
|
site/htdocs/static/common/js/captcha.min.js.map
|
||||||
site/htdocs/static/common/js/confirm.js
|
site/htdocs/static/common/js/confirm.js
|
||||||
site/htdocs/static/common/js/confirm.min.js
|
site/htdocs/static/common/js/confirm.min.js
|
||||||
site/htdocs/static/common/js/confirm.min.js.map
|
site/htdocs/static/common/js/confirm.min.js.map
|
||||||
site/htdocs/static/common/js/favapps.js
|
site/htdocs/static/common/js/favapps.js
|
||||||
site/htdocs/static/common/js/favapps.min.js
|
site/htdocs/static/common/js/favapps.min.js
|
||||||
site/htdocs/static/common/js/favapps.min.js.map
|
site/htdocs/static/common/js/favapps.min.js.map
|
||||||
|
site/htdocs/static/common/js/globalLogout.js
|
||||||
|
site/htdocs/static/common/js/globalLogout.min.js
|
||||||
|
site/htdocs/static/common/js/globalLogout.min.js.map
|
||||||
site/htdocs/static/common/js/idpchoice.js
|
site/htdocs/static/common/js/idpchoice.js
|
||||||
site/htdocs/static/common/js/idpchoice.min.js
|
site/htdocs/static/common/js/idpchoice.min.js
|
||||||
site/htdocs/static/common/js/idpchoice.min.js.map
|
site/htdocs/static/common/js/idpchoice.min.js.map
|
||||||
|
@ -363,10 +373,12 @@ site/htdocs/static/languages/it.json
|
||||||
site/htdocs/static/languages/nl.json
|
site/htdocs/static/languages/nl.json
|
||||||
site/htdocs/static/languages/pt.json
|
site/htdocs/static/languages/pt.json
|
||||||
site/htdocs/static/languages/ro.json
|
site/htdocs/static/languages/ro.json
|
||||||
|
site/htdocs/static/languages/tr.json
|
||||||
site/htdocs/static/languages/vi.json
|
site/htdocs/static/languages/vi.json
|
||||||
site/htdocs/static/languages/zh.json
|
site/htdocs/static/languages/zh.json
|
||||||
site/templates/bootstrap/2fchoice.tpl
|
site/templates/bootstrap/2fchoice.tpl
|
||||||
site/templates/bootstrap/2fregisters.tpl
|
site/templates/bootstrap/2fregisters.tpl
|
||||||
|
site/templates/bootstrap/captcha.tpl
|
||||||
site/templates/bootstrap/casBack2Url.tpl
|
site/templates/bootstrap/casBack2Url.tpl
|
||||||
site/templates/bootstrap/certificateReset.tpl
|
site/templates/bootstrap/certificateReset.tpl
|
||||||
site/templates/bootstrap/checklogins.tpl
|
site/templates/bootstrap/checklogins.tpl
|
||||||
|
@ -383,6 +395,7 @@ site/templates/bootstrap/decryptvalue.tpl
|
||||||
site/templates/bootstrap/error.tpl
|
site/templates/bootstrap/error.tpl
|
||||||
site/templates/bootstrap/ext2fcheck.tpl
|
site/templates/bootstrap/ext2fcheck.tpl
|
||||||
site/templates/bootstrap/footer.tpl
|
site/templates/bootstrap/footer.tpl
|
||||||
|
site/templates/bootstrap/globallogout.tpl
|
||||||
site/templates/bootstrap/gpgform.tpl
|
site/templates/bootstrap/gpgform.tpl
|
||||||
site/templates/bootstrap/header.tpl
|
site/templates/bootstrap/header.tpl
|
||||||
site/templates/bootstrap/idpchoice.tpl
|
site/templates/bootstrap/idpchoice.tpl
|
||||||
|
@ -435,6 +448,7 @@ site/templates/common/mail/fi.json
|
||||||
site/templates/common/mail/fr.json
|
site/templates/common/mail/fr.json
|
||||||
site/templates/common/mail/it.json
|
site/templates/common/mail/it.json
|
||||||
site/templates/common/mail/ms.json
|
site/templates/common/mail/ms.json
|
||||||
|
site/templates/common/mail/tr.json
|
||||||
site/templates/common/mail/vi.json
|
site/templates/common/mail/vi.json
|
||||||
site/templates/common/mail/zh_CN.json
|
site/templates/common/mail/zh_CN.json
|
||||||
site/templates/common/mail_2fcode.tpl
|
site/templates/common/mail_2fcode.tpl
|
||||||
|
@ -521,6 +535,8 @@ t/32-Auth-and-issuer-OIDC-implicit-no-token.t
|
||||||
t/32-Auth-and-issuer-OIDC-implicit.t
|
t/32-Auth-and-issuer-OIDC-implicit.t
|
||||||
t/32-Auth-and-issuer-OIDC-sorted.t
|
t/32-Auth-and-issuer-OIDC-sorted.t
|
||||||
t/32-CAS-10.t
|
t/32-CAS-10.t
|
||||||
|
t/32-OIDC-Offline-Session.t
|
||||||
|
t/32-OIDC-Refresh-Token.t
|
||||||
t/32-OIDC-RP-rule.t
|
t/32-OIDC-RP-rule.t
|
||||||
t/32-OIDC-Token-Introspection.t
|
t/32-OIDC-Token-Introspection.t
|
||||||
t/32-OIDC-Token-Security.t
|
t/32-OIDC-Token-Security.t
|
||||||
|
@ -575,6 +591,8 @@ t/43-MailPasswordReset-with-token.t
|
||||||
t/43-MailPasswordReset.t
|
t/43-MailPasswordReset.t
|
||||||
t/44-CertificateResetByMail-LDAP.t
|
t/44-CertificateResetByMail-LDAP.t
|
||||||
t/50-IssuerGet.t
|
t/50-IssuerGet.t
|
||||||
|
t/57-GlobalLogout-without-Timer.t
|
||||||
|
t/57-GlobalLogout.t
|
||||||
t/58-DecryptValue-with-custom-function.t
|
t/58-DecryptValue-with-custom-function.t
|
||||||
t/58-DecryptValue-with-internal-function.t
|
t/58-DecryptValue-with-internal-function.t
|
||||||
t/59-Double-cookies-for-a-Single-session.t
|
t/59-Double-cookies-for-a-Single-session.t
|
||||||
|
@ -587,6 +605,7 @@ t/61-ForceAuthn.t
|
||||||
t/61-GrantSession.t
|
t/61-GrantSession.t
|
||||||
t/61-Session-ActivityTimeout.t
|
t/61-Session-ActivityTimeout.t
|
||||||
t/61-Session-Timeout.t
|
t/61-Session-Timeout.t
|
||||||
|
t/62-Refresh-plugin.t
|
||||||
t/62-SingleSession.t
|
t/62-SingleSession.t
|
||||||
t/62-UpgradeSession.t
|
t/62-UpgradeSession.t
|
||||||
t/63-History.t
|
t/63-History.t
|
||||||
|
@ -667,4 +686,5 @@ t/test-psgi.pm
|
||||||
t/testslapd/confs-sessions.ldif
|
t/testslapd/confs-sessions.ldif
|
||||||
t/testslapd/slapd.ldif
|
t/testslapd/slapd.ldif
|
||||||
t/testslapd/users.ldif
|
t/testslapd/users.ldif
|
||||||
|
t/Time-Fake.pm
|
||||||
t/vrfyOTP.pl
|
t/vrfyOTP.pl
|
||||||
|
|
|
@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::2F::Ext2F;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_BADCREDENTIALS
|
PE_BADOTP
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_FORMEMPTY
|
PE_FORMEMPTY
|
||||||
PE_OK
|
PE_OK
|
||||||
|
@ -119,7 +119,7 @@ sub verify {
|
||||||
$self->userLogger->warn( 'Second factor failed for '
|
$self->userLogger->warn( 'Second factor failed for '
|
||||||
. $session->{ $self->conf->{whatToTrace} } );
|
. $session->{ $self->conf->{whatToTrace} } );
|
||||||
$self->logger->error("External verify command failed (code $c)");
|
$self->logger->error("External verify command failed (code $c)");
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ sub verify {
|
||||||
|
|
||||||
$self->userLogger->warn( 'Second factor failed for '
|
$self->userLogger->warn( 'Second factor failed for '
|
||||||
. $session->{ $self->conf->{whatToTrace} } );
|
. $session->{ $self->conf->{whatToTrace} } );
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
# system() is used with an array to avoid shell injection
|
# system() is used with an array to avoid shell injection
|
||||||
|
|
|
@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::2F::Mail2F;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_BADCREDENTIALS
|
PE_BADOTP
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_FORMEMPTY
|
PE_FORMEMPTY
|
||||||
PE_OK
|
PE_OK
|
||||||
|
@ -147,7 +147,7 @@ sub verify {
|
||||||
|
|
||||||
$self->userLogger->warn( 'Second factor failed for '
|
$self->userLogger->warn( 'Second factor failed for '
|
||||||
. $session->{ $self->conf->{whatToTrace} } );
|
. $session->{ $self->conf->{whatToTrace} } );
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::2F::REST;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_BADCREDENTIALS
|
PE_BADOTP
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_FORMEMPTY
|
PE_FORMEMPTY
|
||||||
PE_OK
|
PE_OK
|
||||||
|
@ -139,7 +139,7 @@ sub verify {
|
||||||
unless ( $res->{result} ) {
|
unless ( $res->{result} ) {
|
||||||
$self->userLogger->warn( 'REST Second factor failed for '
|
$self->userLogger->warn( 'REST Second factor failed for '
|
||||||
. $session->{ $self->conf->{whatToTrace} } );
|
. $session->{ $self->conf->{whatToTrace} } );
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
PE_OK;
|
PE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::2F::Radius;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_BADCREDENTIALS
|
PE_BADOTP
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_MALFORMEDUSER
|
PE_MALFORMEDUSER
|
||||||
PE_OK
|
PE_OK
|
||||||
|
@ -107,7 +107,7 @@ sub verify {
|
||||||
. $session->{ $self->conf->{whatToTrace} } );
|
. $session->{ $self->conf->{whatToTrace} } );
|
||||||
$self->logger->warn(
|
$self->logger->warn(
|
||||||
"Radius server replied: " . $self->radius->get_error );
|
"Radius server replied: " . $self->radius->get_error );
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
$self->logger->debug("Radius server accepted 2F credentials");
|
$self->logger->debug("Radius server accepted 2F credentials");
|
||||||
PE_OK;
|
PE_OK;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use JSON qw(from_json to_json);
|
use JSON qw(from_json to_json);
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_BADCREDENTIALS
|
PE_BADOTP
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_FORMEMPTY
|
PE_FORMEMPTY
|
||||||
PE_OK
|
PE_OK
|
||||||
|
@ -99,7 +99,7 @@ sub verify {
|
||||||
|
|
||||||
unless ($secret) {
|
unless ($secret) {
|
||||||
$self->logger->debug("No TOTP secret found");
|
$self->logger->debug("No TOTP secret found");
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $r = $self->verifyCode(
|
my $r = $self->verifyCode(
|
||||||
|
@ -117,7 +117,7 @@ sub verify {
|
||||||
$self->userLogger->notice( 'Invalid TOTP for '
|
$self->userLogger->notice( 'Invalid TOTP for '
|
||||||
. $session->{ $self->conf->{whatToTrace} }
|
. $session->{ $self->conf->{whatToTrace} }
|
||||||
. ')' );
|
. ')' );
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use Mouse;
|
||||||
use JSON qw(from_json to_json);
|
use JSON qw(from_json to_json);
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_BADCREDENTIALS
|
PE_BADOTP
|
||||||
PE_FORMEMPTY
|
PE_FORMEMPTY
|
||||||
PE_OK
|
PE_OK
|
||||||
PE_SENDRESPONSE
|
PE_SENDRESPONSE
|
||||||
|
@ -96,7 +96,7 @@ sub run {
|
||||||
$self->userLogger->warn( 'User '
|
$self->userLogger->warn( 'User '
|
||||||
. $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
. $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
||||||
. ' has no Yubikey registered' );
|
. ' has no Yubikey registered' );
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
$self->logger->debug("Found Yubikey : $yubikey");
|
$self->logger->debug("Found Yubikey : $yubikey");
|
||||||
|
|
||||||
|
@ -149,11 +149,11 @@ sub verify {
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$self->userLogger->warn('Yubikey not registered');
|
$self->userLogger->warn('Yubikey not registered');
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
if ( $self->yubi->otp($code) ne 'OK' ) {
|
if ( $self->yubi->otp($code) ne 'OK' ) {
|
||||||
$self->userLogger->warn('Yubikey verification failed');
|
$self->userLogger->warn('Yubikey verification failed');
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADOTP;
|
||||||
}
|
}
|
||||||
PE_OK;
|
PE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ package Lemonldap::NG::Portal::Auth::AD;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants
|
use Lemonldap::NG::Portal::Main::Constants
|
||||||
qw(PE_OK PE_PP_PASSWORD_EXPIRED PE_PP_CHANGE_AFTER_RESET);
|
qw(PE_OK PE_PP_PASSWORD_EXPIRED PE_PP_CHANGE_AFTER_RESET PE_BADCREDENTIALS);
|
||||||
|
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
|
|
||||||
|
@ -66,7 +66,8 @@ sub authenticate {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
my $res = $self->SUPER::authenticate($req);
|
my $res = $self->SUPER::authenticate($req);
|
||||||
|
|
||||||
my $pls = $self->ldap->getLdapValue( $req->data->{ldapentry}, 'pwdLastSet' );
|
my $pls =
|
||||||
|
$self->ldap->getLdapValue( $req->data->{ldapentry}, 'pwdLastSet' );
|
||||||
my $computed = $self->ldap->getLdapValue( $req->data->{ldapentry},
|
my $computed = $self->ldap->getLdapValue( $req->data->{ldapentry},
|
||||||
'msDS-User-Account-Control-Computed' );
|
'msDS-User-Account-Control-Computed' );
|
||||||
my $_adUac =
|
my $_adUac =
|
||||||
|
@ -75,6 +76,15 @@ sub authenticate {
|
||||||
|
|
||||||
unless ( $res == PE_OK ) {
|
unless ( $res == PE_OK ) {
|
||||||
|
|
||||||
|
# Explicit bad credentials message
|
||||||
|
if ( $req->data->{ldapError}
|
||||||
|
and $req->data->{ldapError} =~ /LdapErr: .* data ([^,]+),.*/ )
|
||||||
|
{
|
||||||
|
if ( $1 eq '52e' ) {
|
||||||
|
return PE_BADCREDENTIALS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Check specific AD attributes
|
# Check specific AD attributes
|
||||||
my $mask = 0xf00000; # mask to get the 8 at 6th position
|
my $mask = 0xf00000; # mask to get the 8 at 6th position
|
||||||
my $expired_flag =
|
my $expired_flag =
|
||||||
|
|
|
@ -152,6 +152,17 @@ sub authForce {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sub setSecurity {
|
||||||
|
# my $self = shift;
|
||||||
|
# my ($req) = @_;
|
||||||
|
# $self->getStack( $req, 'extractFormInfo' ) or return PE_ERROR;
|
||||||
|
# $req->userData->{_combinationTry} ||= 0;
|
||||||
|
# eval {
|
||||||
|
# $req->data->{combinationStack}->[ $req->userData->{_combinationTry} ]
|
||||||
|
# ->[0]->( 'setSecurity', @_ );
|
||||||
|
# };
|
||||||
|
#}
|
||||||
|
|
||||||
## UserDB steps
|
## UserDB steps
|
||||||
###############
|
###############
|
||||||
# Note that UserDB::Combination uses the same object.
|
# Note that UserDB::Combination uses the same object.
|
||||||
|
|
|
@ -6,6 +6,7 @@ use Mouse;
|
||||||
use Lemonldap::NG::Common::FormEncode;
|
use Lemonldap::NG::Common::FormEncode;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_BADURL
|
PE_BADURL
|
||||||
|
PE_BADCREDENTIALS
|
||||||
PE_CONFIRM
|
PE_CONFIRM
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_LOGOUT_OK
|
PE_LOGOUT_OK
|
||||||
|
@ -547,11 +548,12 @@ sub run {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $scope_messages = {
|
my $scope_messages = {
|
||||||
openid => 'yourIdentity',
|
openid => 'yourIdentity',
|
||||||
profile => 'yourProfile',
|
profile => 'yourProfile',
|
||||||
email => 'yourEmail',
|
email => 'yourEmail',
|
||||||
address => 'yourAddress',
|
address => 'yourAddress',
|
||||||
phone => 'yourPhone',
|
phone => 'yourPhone',
|
||||||
|
offline_access => 'yourOffline',
|
||||||
};
|
};
|
||||||
my @list;
|
my @list;
|
||||||
foreach my $requested_scope (
|
foreach my $requested_scope (
|
||||||
|
@ -609,6 +611,47 @@ sub run {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# WIP: Offline access
|
||||||
|
my $offline = 0;
|
||||||
|
if ( $oidc_request->{'scope'} =~ /\boffline_access\b/ ) {
|
||||||
|
$offline = 1;
|
||||||
|
|
||||||
|
# MUST ensure that the prompt parameter contains consent unless
|
||||||
|
# other conditions for processing the request permitting offline
|
||||||
|
# access to the requested resources are in place; unless one or
|
||||||
|
# both of these conditions are fulfilled, then it MUST ignore
|
||||||
|
# the offline_access request,
|
||||||
|
unless ( $bypassConsent
|
||||||
|
or ( $prompt and $prompt =~ /\bconsent\b/ ) )
|
||||||
|
{
|
||||||
|
$self->logger->warn( "Offline access ignored, "
|
||||||
|
. "prompt parameter must contain \"consent\"" );
|
||||||
|
$offline = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# MUST ignore the offline_access request unless the Client is
|
||||||
|
# using a response_type value that would result in an
|
||||||
|
# Authorization Code being returned,
|
||||||
|
if ( $response_type !~ /\bcode\b/ ) {
|
||||||
|
$self->logger->warn( "Offline access incompatible "
|
||||||
|
. "with response type $response_type" );
|
||||||
|
$offline = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ignore offline_access request if not authorized by the RP
|
||||||
|
unless ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsAllowOffline} )
|
||||||
|
{
|
||||||
|
$self->logger->warn(
|
||||||
|
"Offline access not authorized for RP $rp");
|
||||||
|
$offline = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Strip offline_access from scopes from now on
|
||||||
|
$oidc_request->{'scope'} = join " ", grep !/^offline_access$/,
|
||||||
|
split /\s+/, $oidc_request->{'scope'};
|
||||||
|
}
|
||||||
|
|
||||||
# Authorization Code Flow
|
# Authorization Code Flow
|
||||||
if ( $flow eq "authorizationcode" ) {
|
if ( $flow eq "authorizationcode" ) {
|
||||||
|
|
||||||
|
@ -616,14 +659,15 @@ sub run {
|
||||||
my $codeSession = $self->newAuthorizationCode(
|
my $codeSession = $self->newAuthorizationCode(
|
||||||
$rp,
|
$rp,
|
||||||
{
|
{
|
||||||
|
code_challenge => $oidc_request->{'code_challenge'},
|
||||||
|
code_challenge_method =>
|
||||||
|
$oidc_request->{'code_challenge_method'},
|
||||||
|
nonce => $oidc_request->{'nonce'},
|
||||||
|
offline => $offline,
|
||||||
redirect_uri => $oidc_request->{'redirect_uri'},
|
redirect_uri => $oidc_request->{'redirect_uri'},
|
||||||
scope => $oidc_request->{'scope'},
|
scope => $oidc_request->{'scope'},
|
||||||
client_id => $client_id,
|
client_id => $client_id,
|
||||||
user_session_id => $req->id,
|
user_session_id => $req->id,
|
||||||
nonce => $oidc_request->{'nonce'},
|
|
||||||
code_challenge => $oidc_request->{'code_challenge'},
|
|
||||||
code_challenge_method =>
|
|
||||||
$oidc_request->{'code_challenge_method'},
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -687,8 +731,10 @@ sub run {
|
||||||
}
|
}
|
||||||
|
|
||||||
# ID token payload
|
# ID token payload
|
||||||
my $id_token_exp = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
my $id_token_exp =
|
||||||
->{oidcRPMetaDataOptionsIDTokenExpiration};
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceIDTokenExpiration};
|
||||||
$id_token_exp += time;
|
$id_token_exp += time;
|
||||||
|
|
||||||
my $authenticationLevel =
|
my $authenticationLevel =
|
||||||
|
@ -728,12 +774,15 @@ sub run {
|
||||||
$id_token_payload_hash->{'acr'} = $id_token_acr
|
$id_token_payload_hash->{'acr'} = $id_token_acr
|
||||||
if $id_token_acr;
|
if $id_token_acr;
|
||||||
|
|
||||||
if ( $response_type !~ /\btoken\b/ ) {
|
if ( $response_type !~ /\btoken\b/
|
||||||
|
|| $self->force_id_claims($rp) )
|
||||||
|
{
|
||||||
|
|
||||||
# No access_token
|
# No access_token
|
||||||
# Claims must be set in id_token
|
# Claims must be set in id_token
|
||||||
my $claims =
|
my $claims =
|
||||||
$self->buildUserInfoResponse( $oidc_request->{'scope'},
|
$self->buildUserInfoResponseFromId(
|
||||||
|
$oidc_request->{'scope'},
|
||||||
$rp, $req->id );
|
$rp, $req->id );
|
||||||
|
|
||||||
foreach ( keys %$claims ) {
|
foreach ( keys %$claims ) {
|
||||||
|
@ -749,8 +798,10 @@ sub run {
|
||||||
$self->logger->debug("Generated id token: $id_token");
|
$self->logger->debug("Generated id token: $id_token");
|
||||||
|
|
||||||
# Send token response
|
# Send token response
|
||||||
my $expires_in = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
my $expires_in =
|
||||||
->{oidcRPMetaDataOptionsAccessTokenExpiration};
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceAccessTokenExpiration};
|
||||||
|
|
||||||
# Build Response
|
# Build Response
|
||||||
my $response_url = $self->buildImplicitAuthnResponse(
|
my $response_url = $self->buildImplicitAuthnResponse(
|
||||||
|
@ -783,11 +834,12 @@ sub run {
|
||||||
my $codeSession = $self->newAuthorizationCode(
|
my $codeSession = $self->newAuthorizationCode(
|
||||||
$rp,
|
$rp,
|
||||||
{
|
{
|
||||||
|
nonce => $oidc_request->{'nonce'},
|
||||||
|
offline => $offline,
|
||||||
redirect_uri => $oidc_request->{'redirect_uri'},
|
redirect_uri => $oidc_request->{'redirect_uri'},
|
||||||
client_id => $client_id,
|
client_id => $client_id,
|
||||||
scope => $oidc_request->{'scope'},
|
scope => $oidc_request->{'scope'},
|
||||||
user_session_id => $req->id,
|
user_session_id => $req->id,
|
||||||
nonce => $oidc_request->{'nonce'},
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -836,11 +888,13 @@ sub run {
|
||||||
# ID token payload
|
# ID token payload
|
||||||
my $id_token_exp =
|
my $id_token_exp =
|
||||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
->{oidcRPMetaDataOptionsIDTokenExpiration};
|
->{oidcRPMetaDataOptionsIDTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceIDTokenExpiration};
|
||||||
$id_token_exp += time;
|
$id_token_exp += time;
|
||||||
|
|
||||||
my $id_token_acr =
|
my $id_token_acr =
|
||||||
"loa-" . $req->{sessionInfo}->{authenticationLevel};
|
"loa-"
|
||||||
|
. ( $req->{sessionInfo}->{authenticationLevel} || 0 );
|
||||||
|
|
||||||
my $user_id_attribute =
|
my $user_id_attribute =
|
||||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
@ -866,11 +920,13 @@ sub run {
|
||||||
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
|
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
|
||||||
$id_token_payload_hash->{'c_hash'} = $c_hash if $c_hash;
|
$id_token_payload_hash->{'c_hash'} = $c_hash if $c_hash;
|
||||||
|
|
||||||
if ( $response_type !~ /\btoken\b/ ) {
|
if ( $response_type !~ /\btoken\b/
|
||||||
|
|| $self->force_id_claims($rp) )
|
||||||
|
{
|
||||||
|
|
||||||
# No access_token
|
# No access_token
|
||||||
# Claims must be set in id_token
|
# Claims must be set in id_token
|
||||||
my $claims = $self->buildUserInfoResponse(
|
my $claims = $self->buildUserInfoResponseFromId(
|
||||||
$oidc_request->{'scope'},
|
$oidc_request->{'scope'},
|
||||||
$rp, $req->id );
|
$rp, $req->id );
|
||||||
|
|
||||||
|
@ -887,8 +943,10 @@ sub run {
|
||||||
$self->logger->debug("Generated id token: $id_token");
|
$self->logger->debug("Generated id token: $id_token");
|
||||||
}
|
}
|
||||||
|
|
||||||
my $expires_in = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
my $expires_in =
|
||||||
->{oidcRPMetaDataOptionsAccessTokenExpiration};
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceAccessTokenExpiration};
|
||||||
|
|
||||||
# Build Response
|
# Build Response
|
||||||
my $response_url = $self->buildHybridAuthnResponse(
|
my $response_url = $self->buildHybridAuthnResponse(
|
||||||
|
@ -1013,152 +1071,466 @@ sub token {
|
||||||
|
|
||||||
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
|
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
|
||||||
|
|
||||||
# Get code session
|
my $grant_type = $req->param('grant_type');
|
||||||
my $code = $req->param('code');
|
|
||||||
|
|
||||||
unless ($code) {
|
# Autorization Code grant
|
||||||
$self->logger->error("No code found on token endpoint");
|
if ( $grant_type eq 'authorization_code' ) {
|
||||||
return $self->p->sendError( $req, 'invalid_request', 400 );
|
my $code = $req->param('code');
|
||||||
}
|
|
||||||
|
|
||||||
$self->logger->debug("OpenID Connect Code: $code");
|
unless ($code) {
|
||||||
|
$self->logger->error("No code found on token endpoint");
|
||||||
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
my $codeSession = $self->getAuthorizationCode($code);
|
my $codeSession = $self->getAuthorizationCode($code);
|
||||||
|
|
||||||
unless ($codeSession) {
|
unless ($codeSession) {
|
||||||
$self->logger->error("Unable to find OIDC session $code");
|
$self->logger->error("Unable to find OIDC session $code");
|
||||||
return $self->p->sendError( $req, 'invalid_request', 400 );
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check PKCE
|
$codeSession->remove();
|
||||||
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
|
||||||
->{oidcRPMetaDataOptionsRequirePKCE} )
|
# Check PKCE
|
||||||
{
|
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
unless (
|
->{oidcRPMetaDataOptionsRequirePKCE} )
|
||||||
$self->validatePKCEChallenge(
|
|
||||||
$req->param('code_verifier'),
|
|
||||||
$codeSession->data->{'code_challenge'},
|
|
||||||
$codeSession->data->{'code_challenge_method'}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
unless (
|
||||||
|
$self->validatePKCEChallenge(
|
||||||
|
$req->param('code_verifier'),
|
||||||
|
$codeSession->data->{'code_challenge'},
|
||||||
|
$codeSession->data->{'code_challenge_method'}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check we have the same client_id value
|
||||||
|
unless ( $client_id eq $codeSession->data->{client_id} ) {
|
||||||
|
$self->userLogger->error( "Provided client_id does not match "
|
||||||
|
. $codeSession->data->{client_id} );
|
||||||
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
# Check we have the same client_id value
|
# Check we have the same redirect_uri value
|
||||||
unless ( $client_id eq $codeSession->data->{client_id} ) {
|
unless (
|
||||||
$self->userLogger->error( "Provided client_id does not match "
|
$req->param("redirect_uri") eq $codeSession->data->{redirect_uri} )
|
||||||
. $codeSession->data->{client_id} );
|
|
||||||
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check we have the same redirect_uri value
|
|
||||||
unless ( $req->param("redirect_uri") eq $codeSession->data->{redirect_uri} )
|
|
||||||
{
|
|
||||||
$self->userLogger->error( "Provided redirect_uri does not match "
|
|
||||||
. $codeSession->data->{redirect_uri} );
|
|
||||||
return $self->p->sendError( $req, 'invalid_request', 400 );
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get user identifier
|
|
||||||
my $apacheSession =
|
|
||||||
$self->p->getApacheSession( $codeSession->data->{user_session_id},
|
|
||||||
noInfo => 1 );
|
|
||||||
|
|
||||||
unless ($apacheSession) {
|
|
||||||
$self->userLogger->error(
|
|
||||||
"Unable to find user session linked to OIDC session $code");
|
|
||||||
$codeSession->remove();
|
|
||||||
return $self->p->sendError( $req, 'invalid_request', 400 );
|
|
||||||
}
|
|
||||||
|
|
||||||
my $user_id_attribute =
|
|
||||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
|
||||||
->{oidcRPMetaDataOptionsUserIDAttr}
|
|
||||||
|| $self->conf->{whatToTrace};
|
|
||||||
my $user_id = $apacheSession->data->{$user_id_attribute};
|
|
||||||
|
|
||||||
$self->logger->debug("Found corresponding user: $user_id");
|
|
||||||
|
|
||||||
# Generate access_token
|
|
||||||
my $accessTokenSession = $self->newAccessToken(
|
|
||||||
$rp,
|
|
||||||
{
|
{
|
||||||
scope => $codeSession->data->{scope},
|
$self->userLogger->error( "Provided redirect_uri does not match "
|
||||||
rp => $rp,
|
. $codeSession->data->{redirect_uri} );
|
||||||
user_session_id => $apacheSession->id,
|
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
unless ($accessTokenSession) {
|
# Get user identifier
|
||||||
|
my $apacheSession =
|
||||||
|
$self->p->getApacheSession( $codeSession->data->{user_session_id},
|
||||||
|
noInfo => 1 );
|
||||||
|
|
||||||
|
unless ($apacheSession) {
|
||||||
|
$self->userLogger->error("Unable to find user session");
|
||||||
|
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
my $user_id_attribute =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsUserIDAttr}
|
||||||
|
|| $self->conf->{whatToTrace};
|
||||||
|
my $user_id = $apacheSession->data->{$user_id_attribute};
|
||||||
|
|
||||||
|
$self->logger->debug("Found corresponding user: $user_id");
|
||||||
|
|
||||||
|
# Generate access_token
|
||||||
|
my $accessTokenSession = $self->newAccessToken(
|
||||||
|
$rp,
|
||||||
|
{
|
||||||
|
scope => $codeSession->data->{scope},
|
||||||
|
rp => $rp,
|
||||||
|
user_session_id => $apacheSession->id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
unless ($accessTokenSession) {
|
||||||
|
$self->userLogger->error(
|
||||||
|
"Unable to create OIDC session for access_token");
|
||||||
|
|
||||||
|
#FIXME: should be an error 500
|
||||||
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
my $access_token = $accessTokenSession->id;
|
||||||
|
|
||||||
|
$self->logger->debug("Generated access token: $access_token");
|
||||||
|
|
||||||
|
# Generate refresh_token
|
||||||
|
my $refresh_token = undef;
|
||||||
|
|
||||||
|
# For offline access, the refresh token isn't tied to the session ID
|
||||||
|
if ( $codeSession->{data}->{offline} ) {
|
||||||
|
|
||||||
|
# We need to remove _sessionType, _sessionid and _utime from the
|
||||||
|
# session data before storing session data in the refresh token
|
||||||
|
my %userInfo;
|
||||||
|
for my $userKey ( grep !/^(_session|_utime$)/,
|
||||||
|
keys %{ $apacheSession->data } )
|
||||||
|
{
|
||||||
|
$userInfo{$userKey} = $apacheSession->data->{$userKey};
|
||||||
|
}
|
||||||
|
my $refreshTokenSession = $self->newRefreshToken(
|
||||||
|
$rp,
|
||||||
|
{
|
||||||
|
%userInfo,
|
||||||
|
redirect_uri => $codeSession->data->{redirect_uri},
|
||||||
|
scope => $codeSession->data->{scope},
|
||||||
|
client_id => $client_id,
|
||||||
|
_session_uid => $apacheSession->data->{_user},
|
||||||
|
auth_time => $apacheSession->data->{_lastAuthnUTime},
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
unless ($refreshTokenSession) {
|
||||||
|
$self->userLogger->error(
|
||||||
|
"Unable to create OIDC session for refresh_token");
|
||||||
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
$refresh_token = $refreshTokenSession->id;
|
||||||
|
|
||||||
|
$self->logger->debug("Generated refresh token: $refresh_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
# For online access, if configured
|
||||||
|
elsif ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsRefreshToken} )
|
||||||
|
{
|
||||||
|
my $refreshTokenSession = $self->newRefreshToken(
|
||||||
|
$rp,
|
||||||
|
{
|
||||||
|
redirect_uri => $codeSession->data->{redirect_uri},
|
||||||
|
scope => $codeSession->data->{scope},
|
||||||
|
client_id => $client_id,
|
||||||
|
user_session_id => $codeSession->data->{user_session_id},
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
unless ($refreshTokenSession) {
|
||||||
|
$self->userLogger->error(
|
||||||
|
"Unable to create OIDC session for refresh_token");
|
||||||
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
$refresh_token = $refreshTokenSession->id;
|
||||||
|
|
||||||
|
$self->logger->debug("Generated refresh token: $refresh_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compute hash to store in at_hash
|
||||||
|
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenSignAlg};
|
||||||
|
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
|
||||||
|
my $at_hash = $self->createHash( $access_token, $hash_level )
|
||||||
|
if $hash_level;
|
||||||
|
|
||||||
|
# ID token payload
|
||||||
|
my $id_token_exp =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceIDTokenExpiration};
|
||||||
|
$id_token_exp += time;
|
||||||
|
|
||||||
|
my $id_token_acr = "loa-" . $apacheSession->data->{authenticationLevel};
|
||||||
|
|
||||||
|
my $id_token_payload_hash = {
|
||||||
|
iss => $self->conf->{oidcServiceMetaDataIssuer}, # Issuer Identifier
|
||||||
|
sub => $user_id, # Subject Identifier
|
||||||
|
aud => [$client_id], # Audience
|
||||||
|
exp => $id_token_exp, # expiration
|
||||||
|
iat => time, # Issued time
|
||||||
|
auth_time => $apacheSession->data->{_lastAuthnUTime}
|
||||||
|
, # Authentication time
|
||||||
|
acr => $id_token_acr, # Authentication Context Class Reference
|
||||||
|
azp => $client_id, # Authorized party
|
||||||
|
# TODO amr
|
||||||
|
};
|
||||||
|
|
||||||
|
my $nonce = $codeSession->data->{nonce};
|
||||||
|
$id_token_payload_hash->{nonce} = $nonce if defined $nonce;
|
||||||
|
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
|
||||||
|
|
||||||
|
if ( $self->force_id_claims($rp) ) {
|
||||||
|
my $claims =
|
||||||
|
$self->buildUserInfoResponseFromId( $codeSession->data->{'scope'},
|
||||||
|
$rp, $codeSession->data->{user_session_id} );
|
||||||
|
|
||||||
|
foreach ( keys %$claims ) {
|
||||||
|
$id_token_payload_hash->{$_} = $claims->{$_}
|
||||||
|
unless ( $_ eq "sub" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create ID Token
|
||||||
|
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
|
||||||
|
|
||||||
|
$self->logger->debug("Generated id token: $id_token");
|
||||||
|
|
||||||
|
# Send token response
|
||||||
|
my $expires_in =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceAccessTokenExpiration};
|
||||||
|
|
||||||
|
my $token_response = {
|
||||||
|
access_token => $access_token,
|
||||||
|
token_type => 'Bearer',
|
||||||
|
expires_in => $expires_in,
|
||||||
|
id_token => $id_token,
|
||||||
|
( $refresh_token ? ( refresh_token => $refresh_token ) : () ),
|
||||||
|
};
|
||||||
|
|
||||||
|
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
|
||||||
|
unless ( $cRP =~ /\b$rp\b/ ) {
|
||||||
|
$self->p->updateSession( $req, { _oidcConnectedRP => "$rp,$cRP" },
|
||||||
|
$apacheSession->id );
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->logger->debug("Send token response");
|
||||||
|
|
||||||
|
return $self->p->sendJSONresponse( $req, $token_response );
|
||||||
|
}
|
||||||
|
|
||||||
|
# Refresh token
|
||||||
|
elsif ( $grant_type eq 'refresh_token' ) {
|
||||||
|
my $refresh_token = $req->param('refresh_token');
|
||||||
|
|
||||||
|
unless ($refresh_token) {
|
||||||
|
$self->logger->error("Missing refresh_token parameter");
|
||||||
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->logger->debug("OpenID Refresh Token: $refresh_token");
|
||||||
|
|
||||||
|
my $refreshSession = $self->getRefreshToken($refresh_token);
|
||||||
|
|
||||||
|
unless ($refreshSession) {
|
||||||
|
$self->logger->error("Unable to find OIDC session $refresh_token");
|
||||||
|
return $self->p->sendError( $req, 'invalid_request', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check we have the same client_id value
|
||||||
|
unless ( $client_id eq $refreshSession->data->{client_id} ) {
|
||||||
|
$self->userLogger->error( "Provided client_id does not match "
|
||||||
|
. $refreshSession->data->{client_id} );
|
||||||
|
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
my $access_token;
|
||||||
|
my $user_id;
|
||||||
|
my $auth_time;
|
||||||
|
my $session;
|
||||||
|
|
||||||
|
# If this refresh token is tied to a SSO session
|
||||||
|
if ( $refreshSession->data->{user_session_id} ) {
|
||||||
|
my $user_session_id = $refreshSession->data->{user_session_id};
|
||||||
|
$session = $self->p->getApacheSession($user_session_id);
|
||||||
|
|
||||||
|
unless ($session) {
|
||||||
|
$self->logger->error("Unable to find user session");
|
||||||
|
return $self->returnBearerError( 'invalid_request',
|
||||||
|
'Invalid request', 401 );
|
||||||
|
}
|
||||||
|
|
||||||
|
my $user_id_attribute =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsUserIDAttr}
|
||||||
|
|| $self->conf->{whatToTrace};
|
||||||
|
$user_id = $session->data->{$user_id_attribute};
|
||||||
|
|
||||||
|
$auth_time = $session->data->{_lastAuthnUTime};
|
||||||
|
|
||||||
|
# Generate access_token
|
||||||
|
my $accessTokenSession = $self->newAccessToken(
|
||||||
|
$rp,
|
||||||
|
{
|
||||||
|
scope => $refreshSession->data->{scope},
|
||||||
|
rp => $rp,
|
||||||
|
user_session_id => $user_session_id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
unless ($accessTokenSession) {
|
||||||
|
$self->userLogger->error(
|
||||||
|
"Unable to create OIDC session for access_token");
|
||||||
|
return $self->p->sendError( $req,
|
||||||
|
'Unable to create Access Token', 500 );
|
||||||
|
}
|
||||||
|
|
||||||
|
$access_token = $accessTokenSession->id;
|
||||||
|
|
||||||
|
$self->logger->debug("Generated access token: $access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Else, we are in an offline session
|
||||||
|
else {
|
||||||
|
|
||||||
|
# Lookup attributes and macros for user
|
||||||
|
$req->user( $refreshSession->data->{_session_uid} );
|
||||||
|
$req->steps( [
|
||||||
|
'getUser', @{ $self->p->betweenAuthAndData },
|
||||||
|
'setSessionInfo', 'setMacros',
|
||||||
|
'setGroups', 'setLocalGroups',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$req->{error} = $self->p->process($req);
|
||||||
|
|
||||||
|
if ( $req->error > 0 ) {
|
||||||
|
|
||||||
|
# PE_BADCREDENTIAL is returned by UserDB modules when the user was
|
||||||
|
# explicitely not found. And not in case of temporary failures
|
||||||
|
if ( $req->error == PE_BADCREDENTIALS ) {
|
||||||
|
$self->logger->error( "User: "
|
||||||
|
. $req->user
|
||||||
|
. " no longer exists, removing offline session" );
|
||||||
|
$refreshSession->remove;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->logger->error(
|
||||||
|
"Could not resolve user: " . $req->user );
|
||||||
|
}
|
||||||
|
return $self->p->sendError( $req, 'invalid_grant', 400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup sessionInfo
|
||||||
|
delete $req->sessionInfo->{_utime};
|
||||||
|
delete $req->sessionInfo->{_startTime};
|
||||||
|
|
||||||
|
# Update refresh session
|
||||||
|
$self->updateRefreshToken( $refreshSession->id, $req->sessionInfo );
|
||||||
|
$session = $refreshSession;
|
||||||
|
for ( keys %{ $req->sessionInfo } ) {
|
||||||
|
$refreshSession->data->{$_} = $req->sessionInfo->{$_};
|
||||||
|
}
|
||||||
|
|
||||||
|
my $user_id_attribute =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsUserIDAttr}
|
||||||
|
|| $self->conf->{whatToTrace};
|
||||||
|
$user_id = $req->sessionInfo->{$user_id_attribute};
|
||||||
|
$self->logger->debug("Found corresponding user: $user_id");
|
||||||
|
|
||||||
|
$auth_time = $refreshSession->data->{auth_time};
|
||||||
|
|
||||||
|
# Generate access_token
|
||||||
|
my $accessTokenSession = $self->newAccessToken(
|
||||||
|
$rp,
|
||||||
|
{
|
||||||
|
scope => $refreshSession->data->{scope},
|
||||||
|
rp => $rp,
|
||||||
|
offline_session_id => $refreshSession->id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
unless ($accessTokenSession) {
|
||||||
|
$self->userLogger->error(
|
||||||
|
"Unable to create OIDC session for access_token");
|
||||||
|
return $self->p->sendError( $req,
|
||||||
|
'Unable to create Access Token', 500 );
|
||||||
|
}
|
||||||
|
|
||||||
|
$access_token = $accessTokenSession->id;
|
||||||
|
|
||||||
|
$self->logger->debug("Generated access token: $access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compute hash to store in at_hash
|
||||||
|
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenSignAlg};
|
||||||
|
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
|
||||||
|
my $at_hash = $self->createHash( $access_token, $hash_level )
|
||||||
|
if $hash_level;
|
||||||
|
|
||||||
|
# ID token payload
|
||||||
|
my $id_token_exp =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsIDTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceIDTokenExpiration};
|
||||||
|
$id_token_exp += time;
|
||||||
|
|
||||||
|
# Authentication level using refresh tokens should probably stay at 0
|
||||||
|
my $id_token_acr = "loa-0";
|
||||||
|
|
||||||
|
my $id_token_payload_hash = {
|
||||||
|
iss => $self->conf->{oidcServiceMetaDataIssuer}, # Issuer Identifier
|
||||||
|
sub => $user_id, # Subject Identifier
|
||||||
|
aud => [$client_id], # Audience
|
||||||
|
exp => $id_token_exp, # expiration
|
||||||
|
iat => time, # Issued time
|
||||||
|
# TODO: is this the right value when using refresh tokens??
|
||||||
|
auth_time => $auth_time, # Authentication time
|
||||||
|
acr => $id_token_acr, # Authentication Context Class Reference
|
||||||
|
azp => $client_id, # Authorized party
|
||||||
|
# TODO amr
|
||||||
|
};
|
||||||
|
|
||||||
|
my $nonce = $refreshSession->data->{nonce};
|
||||||
|
$id_token_payload_hash->{nonce} = $nonce if defined $nonce;
|
||||||
|
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
|
||||||
|
|
||||||
|
# If we forced sending claims in ID token
|
||||||
|
if ( $self->force_id_claims($rp) ) {
|
||||||
|
my $claims =
|
||||||
|
$self->buildUserInfoResponse( $refreshSession->data->{scope},
|
||||||
|
$rp, $session );
|
||||||
|
|
||||||
|
foreach ( keys %$claims ) {
|
||||||
|
$id_token_payload_hash->{$_} = $claims->{$_}
|
||||||
|
unless ( $_ eq "sub" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create ID Token
|
||||||
|
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
|
||||||
|
|
||||||
|
$self->logger->debug("Generated id token: $id_token");
|
||||||
|
|
||||||
|
# Send token response
|
||||||
|
my $expires_in =
|
||||||
|
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||||
|
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||||
|
|| $self->conf->{oidcServiceAccessTokenExpiration};
|
||||||
|
|
||||||
|
my $token_response = {
|
||||||
|
access_token => $access_token,
|
||||||
|
token_type => 'Bearer',
|
||||||
|
expires_in => $expires_in,
|
||||||
|
id_token => $id_token,
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
#my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
|
||||||
|
#unless ( $cRP =~ /\b$rp\b/ ) {
|
||||||
|
# $self->p->updateSession( $req, { _oidcConnectedRP => "$rp,$cRP" },
|
||||||
|
# $apacheSession->id );
|
||||||
|
#}
|
||||||
|
|
||||||
|
$self->logger->debug("Send token response");
|
||||||
|
|
||||||
|
return $self->p->sendJSONresponse( $req, $token_response );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unknown or unspecified grant type
|
||||||
|
else {
|
||||||
$self->userLogger->error(
|
$self->userLogger->error(
|
||||||
"Unable to create OIDC session for access_token");
|
$grant_type
|
||||||
$codeSession->remove();
|
? "Missing grant_type parameter"
|
||||||
return $self->p->sendError( $req, 'invalid_request', 400 );
|
: "Unknown grant type: $grant_type"
|
||||||
|
);
|
||||||
|
return $self->p->sendError( $req, 'unsupported_grant_type', 400 );
|
||||||
}
|
}
|
||||||
|
|
||||||
my $access_token = $accessTokenSession->id;
|
|
||||||
|
|
||||||
$self->logger->debug("Generated access token: $access_token");
|
|
||||||
|
|
||||||
# Compute hash to store in at_hash
|
|
||||||
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
|
||||||
->{oidcRPMetaDataOptionsIDTokenSignAlg};
|
|
||||||
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
|
|
||||||
my $at_hash = $self->createHash( $access_token, $hash_level )
|
|
||||||
if $hash_level;
|
|
||||||
|
|
||||||
# ID token payload
|
|
||||||
my $id_token_exp = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
|
||||||
->{oidcRPMetaDataOptionsIDTokenExpiration};
|
|
||||||
$id_token_exp += time;
|
|
||||||
|
|
||||||
my $id_token_acr = "loa-" . $apacheSession->data->{authenticationLevel};
|
|
||||||
|
|
||||||
my $id_token_payload_hash = {
|
|
||||||
iss => $self->iss,
|
|
||||||
sub => $user_id, # Subject Identifier
|
|
||||||
aud => [$client_id], # Audience
|
|
||||||
exp => $id_token_exp, # expiration
|
|
||||||
iat => time, # Issued time
|
|
||||||
auth_time => $apacheSession->data->{_lastAuthnUTime}
|
|
||||||
, # Authentication time
|
|
||||||
acr => $id_token_acr, # Authentication Context Class Reference
|
|
||||||
azp => $client_id, # Authorized party
|
|
||||||
# TODO amr
|
|
||||||
};
|
|
||||||
|
|
||||||
my $nonce = $codeSession->data->{nonce};
|
|
||||||
$id_token_payload_hash->{nonce} = $nonce if defined $nonce;
|
|
||||||
$id_token_payload_hash->{'at_hash'} = $at_hash if $at_hash;
|
|
||||||
|
|
||||||
# Create ID Token
|
|
||||||
my $id_token = $self->createIDToken( $id_token_payload_hash, $rp );
|
|
||||||
|
|
||||||
$self->logger->debug("Generated id token: $id_token");
|
|
||||||
|
|
||||||
# Send token response
|
|
||||||
my $expires_in = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
|
||||||
->{oidcRPMetaDataOptionsAccessTokenExpiration};
|
|
||||||
|
|
||||||
my $token_response = {
|
|
||||||
access_token => $access_token,
|
|
||||||
token_type => 'Bearer',
|
|
||||||
expires_in => $expires_in,
|
|
||||||
id_token => $id_token,
|
|
||||||
};
|
|
||||||
|
|
||||||
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
|
|
||||||
unless ( $cRP =~ /\b$rp\b/ ) {
|
|
||||||
$self->p->updateSession( $req, { _oidcConnectedRP => "$rp,$cRP" },
|
|
||||||
$apacheSession->id );
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->logger->debug("Send token response");
|
|
||||||
|
|
||||||
$codeSession->remove();
|
|
||||||
return $self->p->sendJSONresponse( $req, $token_response );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Handle userinfo endpoint
|
# Handle userinfo endpoint
|
||||||
|
@ -1190,8 +1562,39 @@ sub userInfo {
|
||||||
my $rp = $accessTokenSession->data->{rp};
|
my $rp = $accessTokenSession->data->{rp};
|
||||||
my $user_session_id = $accessTokenSession->data->{user_session_id};
|
my $user_session_id = $accessTokenSession->data->{user_session_id};
|
||||||
|
|
||||||
|
my $session;
|
||||||
|
|
||||||
|
# If using a refreshed access token
|
||||||
|
if ($user_session_id) {
|
||||||
|
|
||||||
|
# Get user identifier
|
||||||
|
$session = $self->p->getApacheSession($user_session_id);
|
||||||
|
|
||||||
|
unless ($session) {
|
||||||
|
$self->logger->error("Unable to find user session");
|
||||||
|
return $self->returnBearerError( 'invalid_request',
|
||||||
|
'Invalid request', 401 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my $offline_session_id =
|
||||||
|
$accessTokenSession->data->{offline_session_id};
|
||||||
|
unless ($offline_session_id) {
|
||||||
|
return $self->returnBearerError( 'invalid_request',
|
||||||
|
'Invalid request', 401 );
|
||||||
|
}
|
||||||
|
|
||||||
|
$session = $self->getRefreshToken($offline_session_id);
|
||||||
|
|
||||||
|
unless ($session) {
|
||||||
|
$self->logger->error("Unable to find refresh session");
|
||||||
|
return $self->returnBearerError( 'invalid_request',
|
||||||
|
'Invalid request', 401 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
my $userinfo_response =
|
my $userinfo_response =
|
||||||
$self->buildUserInfoResponse( $scope, $rp, $user_session_id );
|
$self->buildUserInfoResponse( $scope, $rp, $session );
|
||||||
unless ($userinfo_response) {
|
unless ($userinfo_response) {
|
||||||
return $self->returnBearerError( 'invalid_request', 'Invalid request',
|
return $self->returnBearerError( 'invalid_request', 'Invalid request',
|
||||||
401 );
|
401 );
|
||||||
|
|
|
@ -1717,7 +1717,8 @@ sub sloServer {
|
||||||
$req->data->{samlSLOCalled} = 1;
|
$req->data->{samlSLOCalled} = 1;
|
||||||
|
|
||||||
# Launch normal logout and ignore errors
|
# Launch normal logout and ignore errors
|
||||||
$self->p->do( $req, [ @{ $self->p->beforeLogout }, 'deleteSession' ] );
|
$req->steps( [ @{ $self->p->beforeLogout }, 'deleteSession' ] );
|
||||||
|
$self->p->process($req);
|
||||||
|
|
||||||
# Signature
|
# Signature
|
||||||
my $signSLOMessage = $self->conf->{samlSPMetaDataOptions}->{$spConfKey}
|
my $signSLOMessage = $self->conf->{samlSPMetaDataOptions}->{$spConfKey}
|
||||||
|
|
|
@ -114,7 +114,14 @@ sub init {
|
||||||
sub getUser {
|
sub getUser {
|
||||||
my ( $self, $req, %args ) = @_;
|
my ( $self, $req, %args ) = @_;
|
||||||
|
|
||||||
return PE_LDAPCONNECTFAILED unless $self->ldap and $self->bind();
|
$self->validateLdap;
|
||||||
|
|
||||||
|
unless ( $self->ldap ) {
|
||||||
|
return PE_LDAPCONNECTFAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->bind();
|
||||||
|
|
||||||
my $mesg = $self->ldap->search(
|
my $mesg = $self->ldap->search(
|
||||||
base => $self->conf->{ldapBase},
|
base => $self->conf->{ldapBase},
|
||||||
scope => 'sub',
|
scope => 'sub',
|
||||||
|
|
|
@ -249,6 +249,9 @@ sub userBind {
|
||||||
if ( $mesg->code == 0 ) {
|
if ( $mesg->code == 0 ) {
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$req->data->{ldapError} = $mesg->error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$self->{portal}->userLogger->warn("Bad password for $req->{user}");
|
$self->{portal}->userLogger->warn("Bad password for $req->{user}");
|
||||||
return PE_BADCREDENTIALS;
|
return PE_BADCREDENTIALS;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package Lemonldap::NG::Portal::Lib::Notifications::JSON;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use JSON qw(from_json);
|
use JSON qw(from_json);
|
||||||
|
use POSIX qw(strftime);
|
||||||
|
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
|
|
||||||
|
@ -34,18 +35,22 @@ sub checkForNotifications {
|
||||||
return 0 unless ($notifs);
|
return 0 unless ($notifs);
|
||||||
|
|
||||||
# Transform notifications
|
# Transform notifications
|
||||||
my $i = 0; #Files count
|
my $i = 0; # Files count
|
||||||
my @res;
|
my @res;
|
||||||
|
my $now = strftime "%Y-%m-%d", localtime;
|
||||||
|
|
||||||
foreach my $file ( values %$notifs ) {
|
foreach my $file ( values %$notifs ) {
|
||||||
my $json = from_json( $file, { allow_nonref => 1 } );
|
my $json = eval { from_json( $file, { allow_nonref => 1 } ) };
|
||||||
my $j = 0; #Notifications count
|
$self->userLogger->warn(
|
||||||
|
"Bad JSON file: a notification for $uid was not done ($@)")
|
||||||
|
if ($@);
|
||||||
|
my $j = 0; # Notifications count
|
||||||
$json = [$json] unless ( ref $json eq 'ARRAY' );
|
$json = [$json] unless ( ref $json eq 'ARRAY' );
|
||||||
LOOP: foreach my $notif ( @{$json} ) {
|
LOOP: foreach my $notif ( @{$json} ) {
|
||||||
|
|
||||||
# Get the reference
|
# Get the reference
|
||||||
my $reference = $notif->{reference};
|
my $reference = $notif->{reference};
|
||||||
|
$self->logger->debug("Get reference: $reference");
|
||||||
$self->logger->debug("Get reference $reference");
|
|
||||||
|
|
||||||
# Check it in session
|
# Check it in session
|
||||||
if ( exists $req->{sessionInfo}->{"notification_$reference"} ) {
|
if ( exists $req->{sessionInfo}->{"notification_$reference"} ) {
|
||||||
|
@ -55,6 +60,35 @@ sub checkForNotifications {
|
||||||
"Notification $reference was already accepted");
|
"Notification $reference was already accepted");
|
||||||
next LOOP;
|
next LOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check date
|
||||||
|
my $date = $notif->{date};
|
||||||
|
$self->logger->debug("Get date: $date");
|
||||||
|
unless ( $date and $date =~ /\b\d{4}-\d{2}-\d{2}\b/ ) {
|
||||||
|
$self->logger->error('Malformed date');
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $date le $now ) {
|
||||||
|
$self->logger->debug('Notification date not reached');
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check condition if any
|
||||||
|
if ( my $condition = $notif->{condition} ) {
|
||||||
|
$self->logger->debug("Get condition $condition");
|
||||||
|
$condition = $self->p->HANDLER->substitute($condition);
|
||||||
|
unless ( $condition = $self->p->HANDLER->buildSub($condition) )
|
||||||
|
{
|
||||||
|
$self->logger->error( 'Notification condition error: '
|
||||||
|
. $self->p->HANDLER->tsv->{jail}->error );
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $condition->( $req, $req->sessionInfo ) ) {
|
||||||
|
$self->logger->debug(
|
||||||
|
'Notification condition not authorized');
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
push @res, $notif;
|
push @res, $notif;
|
||||||
$j++;
|
$j++;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +104,7 @@ sub checkForNotifications {
|
||||||
|
|
||||||
# Stop here if nothing to display
|
# Stop here if nothing to display
|
||||||
return 0 unless $i;
|
return 0 unless $i;
|
||||||
|
$self->userLogger->info("$i pending notification(s) found for $uid");
|
||||||
|
|
||||||
# Returns HTML fragment
|
# Returns HTML fragment
|
||||||
return $form;
|
return $form;
|
||||||
|
@ -114,8 +149,9 @@ sub getNotifBack {
|
||||||
$self->p->importHandlerData($req);
|
$self->p->importHandlerData($req);
|
||||||
my $uid = $req->sessionInfo->{ $self->notifObject->notifField };
|
my $uid = $req->sessionInfo->{ $self->notifObject->notifField };
|
||||||
|
|
||||||
my ( $notifs, $forUser );
|
# ALL notifications are returned here => Need to check active ones only
|
||||||
eval { ( $notifs, $forUser ) = $self->notifObject->getNotifications($uid) };
|
my ( $notifs, $forUser ) =
|
||||||
|
eval { $self->notifObject->getNotifications($uid) };
|
||||||
return $self->p->sendError( $req, $@, 500 ) if ($@);
|
return $self->p->sendError( $req, $@, 500 ) if ($@);
|
||||||
|
|
||||||
if ($notifs) {
|
if ($notifs) {
|
||||||
|
@ -134,6 +170,7 @@ sub getNotifBack {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $result = 1;
|
my $result = 1;
|
||||||
|
my $now = strftime "%Y-%m-%d", localtime;
|
||||||
foreach my $fileName ( keys %$notifs ) {
|
foreach my $fileName ( keys %$notifs ) {
|
||||||
my $file = $notifs->{$fileName};
|
my $file = $notifs->{$fileName};
|
||||||
my $fileResult = 1;
|
my $fileResult = 1;
|
||||||
|
@ -141,14 +178,48 @@ sub getNotifBack {
|
||||||
$json = [$json] unless ( ref $json eq 'ARRAY' );
|
$json = [$json] unless ( ref $json eq 'ARRAY' );
|
||||||
|
|
||||||
# Get pending notifications and verify that they have been accepted
|
# Get pending notifications and verify that they have been accepted
|
||||||
foreach my $notif (@$json) {
|
LOOP: foreach my $notif (@$json) {
|
||||||
my $reference = $notif->{reference};
|
my $reference = $notif->{reference};
|
||||||
|
|
||||||
|
# Check date
|
||||||
|
my $date = $notif->{date};
|
||||||
|
$self->logger->debug("Get date: $date");
|
||||||
|
unless ( $date and $date =~ /\b\d{4}-\d{2}-\d{2}\b/ ) {
|
||||||
|
$self->logger->error('Malformed date');
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $date le $now ) {
|
||||||
|
$self->logger->debug('Notification date not reached');
|
||||||
|
$fileResult = 0; # Do not delete notification
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check condition if any
|
||||||
|
if ( my $condition = $notif->{condition} ) {
|
||||||
|
$self->logger->debug("Get condition $condition");
|
||||||
|
$condition = $self->p->HANDLER->substitute($condition);
|
||||||
|
unless ( $condition =
|
||||||
|
$self->p->HANDLER->buildSub($condition) )
|
||||||
|
{
|
||||||
|
$self->logger->error( 'Notification condition error: '
|
||||||
|
. $self->p->HANDLER->tsv->{jail}->error );
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $condition->( $req, $req->sessionInfo ) ) {
|
||||||
|
$self->logger->debug(
|
||||||
|
'Notification condition not authorized');
|
||||||
|
$fileResult = 0; # Do not delete notification
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Check if this pending notification has been seen
|
# Check if this pending notification has been seen
|
||||||
if ( my $refId = $refs->{$reference} ) {
|
if ( my $refId = $refs->{$reference} ) {
|
||||||
|
|
||||||
# Verity that checkboxes have been checked
|
# Verity that checkboxes have been checked
|
||||||
if ( $notif->{check} ) {
|
if ( $notif->{check} ) {
|
||||||
|
$notif->{check} = [ $notif->{check} ]
|
||||||
|
unless ( ref( $notif->{check} ) eq 'ARRAY' );
|
||||||
if ( my $toCheckCount = @{ $notif->{check} } ) {
|
if ( my $toCheckCount = @{ $notif->{check} } ) {
|
||||||
unless ($checks->{$refId}
|
unless ($checks->{$refId}
|
||||||
and $toCheckCount == @{ $checks->{$refId} } )
|
and $toCheckCount == @{ $checks->{$refId} } )
|
||||||
|
@ -157,7 +228,7 @@ sub getNotifBack {
|
||||||
"$uid has not accepted notification $reference"
|
"$uid has not accepted notification $reference"
|
||||||
);
|
);
|
||||||
$result = $fileResult = 0;
|
$result = $fileResult = 0;
|
||||||
next;
|
next LOOP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,10 +236,10 @@ sub getNotifBack {
|
||||||
else {
|
else {
|
||||||
# Current pending notification has not been found in
|
# Current pending notification has not been found in
|
||||||
# request
|
# request
|
||||||
$result = $fileResult = 0;
|
|
||||||
$self->logger->debug(
|
$self->logger->debug(
|
||||||
'Current pending notification has not been found');
|
'Current pending notification has not been found');
|
||||||
next;
|
$result = $fileResult = 0;
|
||||||
|
next LOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Register acceptation
|
# Register acceptation
|
||||||
|
@ -217,6 +288,8 @@ sub toForm {
|
||||||
@notifs = map {
|
@notifs = map {
|
||||||
$i++;
|
$i++;
|
||||||
if ( $_->{check} ) {
|
if ( $_->{check} ) {
|
||||||
|
$_->{check} = [ $_->{check} ]
|
||||||
|
unless ( ref( $_->{check} ) eq 'ARRAY' );
|
||||||
my $j = 0;
|
my $j = 0;
|
||||||
$_->{check} =
|
$_->{check} =
|
||||||
[ map { $j++; { id => '1x' . $i . 'x' . $j, value => $_ } }
|
[ map { $j++; { id => '1x' . $i . 'x' . $j, value => $_ } }
|
||||||
|
@ -238,8 +311,10 @@ sub notificationServer {
|
||||||
my ( $res, $err );
|
my ( $res, $err );
|
||||||
if ( $req->method =~ /^POST$/i ) {
|
if ( $req->method =~ /^POST$/i ) {
|
||||||
$self->p->logger->debug("POST request");
|
$self->p->logger->debug("POST request");
|
||||||
( $res, $err ) =
|
( $res, $err ) = eval {
|
||||||
eval { $self->notifObject->newNotification( $req->content ) };
|
$self->notifObject->newNotification( $req->content,
|
||||||
|
$self->conf->{notificationDefaultCond} );
|
||||||
|
};
|
||||||
return $self->p->sendError( $req, $@, 500 ) if ($@);
|
return $self->p->sendError( $req, $@, 500 ) if ($@);
|
||||||
}
|
}
|
||||||
elsif ( $req->method =~ /^GET$/i ) {
|
elsif ( $req->method =~ /^GET$/i ) {
|
||||||
|
@ -252,10 +327,8 @@ sub notificationServer {
|
||||||
$res = [];
|
$res = [];
|
||||||
foreach my $notif ( keys %$notifs ) {
|
foreach my $notif ( keys %$notifs ) {
|
||||||
$self->p->logger->debug("Found notification $notif");
|
$self->p->logger->debug("Found notification $notif");
|
||||||
my $json;
|
my $json =
|
||||||
eval {
|
eval { from_json( $notifs->{$notif}, { allow_nonref => 1 } ) };
|
||||||
$json = from_json( $notifs->{$notif}, { allow_nonref => 1 } );
|
|
||||||
};
|
|
||||||
return $self->p->sendError( $req, "Unable to decode JSON file: $@",
|
return $self->p->sendError( $req, "Unable to decode JSON file: $@",
|
||||||
400 )
|
400 )
|
||||||
if ($@);
|
if ($@);
|
||||||
|
|
|
@ -4,6 +4,7 @@ use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use XML::LibXML;
|
use XML::LibXML;
|
||||||
use XML::LibXSLT;
|
use XML::LibXSLT;
|
||||||
|
use POSIX qw(strftime);
|
||||||
|
|
||||||
our $VERSION = '2.1.0';
|
our $VERSION = '2.1.0';
|
||||||
|
|
||||||
|
@ -44,6 +45,10 @@ has stylesheet => (
|
||||||
# Underlying notifications storage object (File, DBI, LDAP,...)
|
# Underlying notifications storage object (File, DBI, LDAP,...)
|
||||||
has notifObject => ( is => 'rw' );
|
has notifObject => ( is => 'rw' );
|
||||||
|
|
||||||
|
# Notification server accessors
|
||||||
|
has imported => ( is => 'rw', default => 0 );
|
||||||
|
has server => ( is => 'rw' );
|
||||||
|
|
||||||
# INITIALIZATION
|
# INITIALIZATION
|
||||||
|
|
||||||
sub init {
|
sub init {
|
||||||
|
@ -61,10 +66,12 @@ sub checkForNotifications {
|
||||||
return 0 unless ($notifs);
|
return 0 unless ($notifs);
|
||||||
|
|
||||||
# Transform notifications
|
# Transform notifications
|
||||||
my $i = 0; #Files count
|
my $i = 0; # Files count
|
||||||
|
my $now = strftime "%Y-%m-%d", localtime;
|
||||||
|
|
||||||
foreach my $file ( values %$notifs ) {
|
foreach my $file ( values %$notifs ) {
|
||||||
my $xml = $self->parser->parse_string($file);
|
my $xml = $self->parser->parse_string($file);
|
||||||
my $j = 0; #Notifications count
|
my $j = 0; # Notifications count
|
||||||
LOOP: foreach my $notif (
|
LOOP: foreach my $notif (
|
||||||
eval {
|
eval {
|
||||||
$xml->documentElement->getElementsByTagName('notification');
|
$xml->documentElement->getElementsByTagName('notification');
|
||||||
|
@ -74,7 +81,6 @@ sub checkForNotifications {
|
||||||
|
|
||||||
# Get the reference
|
# Get the reference
|
||||||
my $reference = $notif->getAttribute('reference');
|
my $reference = $notif->getAttribute('reference');
|
||||||
|
|
||||||
$self->logger->debug("Get reference $reference");
|
$self->logger->debug("Get reference $reference");
|
||||||
|
|
||||||
# Check it in session
|
# Check it in session
|
||||||
|
@ -89,21 +95,35 @@ sub checkForNotifications {
|
||||||
next LOOP;
|
next LOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check date
|
||||||
|
my $date = $notif->getAttribute('date');
|
||||||
|
$self->logger->debug("Get date: $date");
|
||||||
|
unless ( $date and $date =~ /\b\d{4}-\d{2}-\d{2}\b/ ) {
|
||||||
|
$self->logger->error('Malformed date');
|
||||||
|
$notif->unbindNode();
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $date le $now ) {
|
||||||
|
$self->logger->debug('Notification date not reached');
|
||||||
|
|
||||||
|
# Remove it from XML
|
||||||
|
$notif->unbindNode();
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
|
||||||
# Check condition if any
|
# Check condition if any
|
||||||
my $condition = $notif->getAttribute('condition');
|
if ( my $condition = $notif->getAttribute('condition') ) {
|
||||||
|
|
||||||
if ($condition) {
|
|
||||||
|
|
||||||
$self->logger->debug("Get condition $condition");
|
$self->logger->debug("Get condition $condition");
|
||||||
$condition = $self->p->HANDLER->substitute($condition);
|
$condition = $self->p->HANDLER->substitute($condition);
|
||||||
unless ( $condition = $self->p->HANDLER->buildSub($condition) )
|
unless ( $condition = $self->p->HANDLER->buildSub($condition) )
|
||||||
{
|
{
|
||||||
$self->logger->error( 'Notification condition error: '
|
$self->logger->error( 'Notification condition error: '
|
||||||
. $self->p->HANDLER->tsv->{jail}->error );
|
. $self->p->HANDLER->tsv->{jail}->error );
|
||||||
|
|
||||||
|
# Remove it from XML
|
||||||
$notif->unbindNode();
|
$notif->unbindNode();
|
||||||
next LOOP;
|
next LOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
unless ( $condition->( $req, $req->sessionInfo ) ) {
|
unless ( $condition->( $req, $req->sessionInfo ) ) {
|
||||||
$self->logger->debug(
|
$self->logger->debug(
|
||||||
'Notification condition not authorized');
|
'Notification condition not authorized');
|
||||||
|
@ -113,7 +133,6 @@ sub checkForNotifications {
|
||||||
next LOOP;
|
next LOOP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$j++;
|
$j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +152,7 @@ sub checkForNotifications {
|
||||||
|
|
||||||
# Stop here if nothing to display
|
# Stop here if nothing to display
|
||||||
return 0 unless $i;
|
return 0 unless $i;
|
||||||
|
$self->userLogger->info("$i pending notification(s) found for $uid");
|
||||||
|
|
||||||
# Returns HTML fragment
|
# Returns HTML fragment
|
||||||
return $form;
|
return $form;
|
||||||
|
@ -177,7 +197,11 @@ sub getNotifBack {
|
||||||
$self->p->importHandlerData($req);
|
$self->p->importHandlerData($req);
|
||||||
my $uid = $req->sessionInfo->{ $self->notifObject->notifField };
|
my $uid = $req->sessionInfo->{ $self->notifObject->notifField };
|
||||||
|
|
||||||
my ( $notifs, $forUser ) = $self->notifObject->getNotifications($uid);
|
# ALL notifications are returned here => Need to check active ones only
|
||||||
|
my ( $notifs, $forUser ) =
|
||||||
|
eval { $self->notifObject->getNotifications($uid) };
|
||||||
|
return $self->p->sendError( $req, $@, 500 ) if ($@);
|
||||||
|
|
||||||
if ($notifs) {
|
if ($notifs) {
|
||||||
|
|
||||||
# Get accepted notifications
|
# Get accepted notifications
|
||||||
|
@ -194,17 +218,51 @@ sub getNotifBack {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $result = 1;
|
my $result = 1;
|
||||||
|
my $now = strftime "%Y-%m-%d", localtime;
|
||||||
foreach my $fileName ( keys %$notifs ) {
|
foreach my $fileName ( keys %$notifs ) {
|
||||||
my $file = $notifs->{$fileName};
|
my $file = $notifs->{$fileName};
|
||||||
my $fileResult = 1;
|
my $fileResult = 1;
|
||||||
my $xml = $self->parser->parse_string($file);
|
my $xml = $self->parser->parse_string($file);
|
||||||
|
|
||||||
# Get pending notifications and verify that they have been accepted
|
# Get pending notifications and verify that they have been accepted
|
||||||
|
LOOP:
|
||||||
foreach my $notif (
|
foreach my $notif (
|
||||||
$xml->documentElement->getElementsByTagName('notification') )
|
$xml->documentElement->getElementsByTagName('notification') )
|
||||||
{
|
{
|
||||||
my $reference = $notif->getAttribute('reference');
|
my $reference = $notif->getAttribute('reference');
|
||||||
|
|
||||||
|
# Check date
|
||||||
|
my $date = $notif->getAttribute('date');
|
||||||
|
$self->logger->debug("Get date: $date");
|
||||||
|
unless ( $date and $date =~ /\b\d{4}-\d{2}-\d{2}\b/ ) {
|
||||||
|
$self->logger->error('Malformed date');
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $date le $now ) {
|
||||||
|
$self->logger->debug('Notification date not reached');
|
||||||
|
$fileResult = 0; # Do not delete notification
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check condition if any
|
||||||
|
if ( my $condition = $notif->getAttribute('condition') ) {
|
||||||
|
$self->logger->debug("Get condition $condition");
|
||||||
|
$condition = $self->p->HANDLER->substitute($condition);
|
||||||
|
unless ( $condition =
|
||||||
|
$self->p->HANDLER->buildSub($condition) )
|
||||||
|
{
|
||||||
|
$self->logger->error( 'Notification condition error: '
|
||||||
|
. $self->p->HANDLER->tsv->{jail}->error );
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
unless ( $condition->( $req, $req->sessionInfo ) ) {
|
||||||
|
$self->logger->debug(
|
||||||
|
'Notification condition not authorized');
|
||||||
|
$fileResult = 0; # Do not delete notification
|
||||||
|
next LOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Check if this pending notification has been seen
|
# Check if this pending notification has been seen
|
||||||
if ( my $refId = $refs->{$reference} ) {
|
if ( my $refId = $refs->{$reference} ) {
|
||||||
|
|
||||||
|
@ -260,7 +318,7 @@ sub getNotifBack {
|
||||||
# launch 'controlUrl' to restore "urldc" using do()
|
# launch 'controlUrl' to restore "urldc" using do()
|
||||||
$self->logger->debug('All pending notifications have been accepted');
|
$self->logger->debug('All pending notifications have been accepted');
|
||||||
$self->p->rebuildCookies($req);
|
$self->p->rebuildCookies($req);
|
||||||
return $self->p->do( $req, ['controlUrl', @{ $self->p->endAuth }] );
|
return $self->p->do( $req, [ 'controlUrl', @{ $self->p->endAuth } ] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# No notifications checked here, this entry point must not be called.
|
# No notifications checked here, this entry point must not be called.
|
||||||
|
@ -271,9 +329,6 @@ sub getNotifBack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has imported => ( is => 'rw', default => 0 );
|
|
||||||
has server => ( is => 'rw' );
|
|
||||||
|
|
||||||
sub notificationServer {
|
sub notificationServer {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
unless ( $self->imported ) {
|
unless ( $self->imported ) {
|
||||||
|
@ -299,7 +354,8 @@ sub notificationServer {
|
||||||
|
|
||||||
sub newNotification {
|
sub newNotification {
|
||||||
my ( $self, $req, $xml ) = @_;
|
my ( $self, $req, $xml ) = @_;
|
||||||
return $self->notifObject->newNotification($xml);
|
return $self->notifObject->newNotification( $xml,
|
||||||
|
$self->conf->{notificationDefaultCond} );
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user