Merge branch '2745' into 'v2.0'

Use portalEnablePasswordDisplay option in password change/reset forms

See merge request lemonldap-ng/lemonldap-ng!265
This commit is contained in:
Christophe Maudoux 2022-05-16 17:21:37 +00:00
commit 91a5aabf0b
17 changed files with 233 additions and 155 deletions

View File

@ -17,7 +17,7 @@ sub defaultValues {
},
'authChoiceParam' => 'lmAuth',
'authentication' => 'Demo',
'available2F' =>
'available2F' =>
'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
'available2FSelfRegistration' => 'TOTP,U2F,WebAuthn,Yubikey',
'bruteForceProtectionLockTimes' => '15, 30, 60, 300, 600',
@ -102,7 +102,7 @@ sub defaultValues {
'globalLogoutTimer' => 1,
'globalStorage' => 'Apache::Session::File',
'globalStorageOptions' => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
@ -175,20 +175,20 @@ sub defaultValues {
'locationRules' => {
'default' => 'deny'
},
'logoutServices' => {},
'macros' => {},
'mail2fActivation' => 0,
'mail2fCodeRegex' => '\\d{6}',
'mailCharset' => 'utf-8',
'mailFrom' => 'noreply@example.com',
'mailSessionKey' => 'mail',
'mailTimeout' => 0,
'mailUrl' => 'http://auth.example.com/resetpwd',
'managerDn' => '',
'managerPassword' => '',
'max2FDevices' => 10,
'max2FDevicesNameLength' => 20,
'multiValuesSeparator' => '; ',
'logoutServices' => {},
'macros' => {},
'mail2fActivation' => 0,
'mail2fCodeRegex' => '\\d{6}',
'mailCharset' => 'utf-8',
'mailFrom' => 'noreply@example.com',
'mailSessionKey' => 'mail',
'mailTimeout' => 0,
'mailUrl' => 'http://auth.example.com/resetpwd',
'managerDn' => '',
'managerPassword' => '',
'max2FDevices' => 10,
'max2FDevicesNameLength' => 20,
'multiValuesSeparator' => '; ',
'mySessionAuthorizedRWKeys' =>
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
'newLocationWarningLocationAttribute' => 'ipAddr',
@ -196,7 +196,7 @@ sub defaultValues {
'newLocationWarningMaxValues' => '0',
'notificationDefaultCond' => '',
'notificationServerPOST' => 1,
'notificationServerSentAttributes' =>
'notificationServerSentAttributes' =>
'uid reference date title subtitle text check',
'notificationsMaxRetrieve' => 3,
'notificationStorage' => 'File',
@ -250,7 +250,7 @@ sub defaultValues {
'passwordPolicyMinUpper' => 0,
'passwordPolicySpecialChar' => '__ALL__',
'passwordResetAllowedRetries' => 3,
'persistentSessionAttributes' =>
'persistentSessionAttributes' =>
'_loginHistory _2fDevices notification_',
'port' => -1,
'portal' => 'http://auth.example.com/',
@ -261,7 +261,7 @@ sub defaultValues {
'portalDisplayGeneratePassword' => 1,
'portalDisplayLoginHistory' => 1,
'portalDisplayLogout' => 1,
'portalDisplayOidcConsents' =>
'portalDisplayOidcConsents' =>
'$_oidcConsents && $_oidcConsents =~ /\\w+/',
'portalDisplayRefreshMyRights' => 1,
'portalDisplayRegister' => 1,
@ -289,11 +289,11 @@ sub defaultValues {
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
'proxy' => 'http://auth.example.com/sessions'
},
'requireToken' => 1,
'rest2fActivation' => 0,
'restAuthnLevel' => 2,
'restClockTolerance' => 15,
'sameSite' => '',
'requireToken' => 1,
'rest2fActivation' => 0,
'restAuthnLevel' => 2,
'restClockTolerance' => 15,
'sameSite' => '',
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
'samlAuthnContextMapKerberos' => 4,
@ -333,7 +333,7 @@ sub defaultValues {
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact',
'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost',
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
'samlSPSSODescriptorSingleLogoutServiceHTTPPost' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' =>
@ -345,7 +345,7 @@ sub defaultValues {
'sfEngine' => '::2F::Engines::Default',
'sfManagerRule' => 1,
'sfRemovedMsgRule' => 0,
'sfRemovedNotifMsg' =>
'sfRemovedNotifMsg' =>
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
'sfRemovedNotifRef' => 'RemoveSF',
'sfRemovedNotifTitle' => 'Second factor notification',

View File

@ -67,7 +67,7 @@ sub types {
'hostname' => {
'form' => 'text',
'msgFail' => '__badHostname__',
'test' =>
'test' =>
qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))?$/
},
'int' => {
@ -257,7 +257,7 @@ m[^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9/\+\r\
'url' => {
'form' => 'text',
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:^$|(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?))/
}
};
@ -802,7 +802,7 @@ sub attributes {
},
'casSrvMetaDataOptionsUrl' => {
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
'type' => 'text'
},
@ -1341,7 +1341,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'domain' => {
'default' => 'example.com',
'msgFail' => '__badDomainName__',
'test' =>
'test' =>
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?$/,
'type' => 'text'
},
@ -1484,7 +1484,7 @@ qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-
},
'globalStorageOptions' => {
'default' => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
@ -1609,7 +1609,7 @@ qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-
'issuerDBGetParameters' => {
'default' => {},
'keyMsgFail' => '__badHostname__',
'keyTest' =>
'keyTest' =>
qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/,
'test' => {
'keyMsgFail' => '__badKeyName__',
@ -2808,7 +2808,7 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
'pdataDomain' => {
'default' => '',
'msgFail' => '__badDomainName__',
'test' =>
'test' =>
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?$/,
'type' => 'text'
},
@ -2829,7 +2829,7 @@ qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-
'portal' => {
'default' => 'http://auth.example.com/',
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
'type' => 'url'
},
@ -3136,7 +3136,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'keyTest' =>
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))(?::\d+)?$/,
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
'type' => 'keyTextContainer'
},
@ -3288,19 +3288,19 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'samlCommonDomainCookieDomain' => {
'msgFail' => '__badDomainName__',
'test' =>
'test' =>
qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/,
'type' => 'text'
},
'samlCommonDomainCookieReader' => {
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
'type' => 'text'
},
'samlCommonDomainCookieWriter' => {
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
'type' => 'text'
},
@ -3317,7 +3317,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'samlDiscoveryProtocolURL' => {
'msgFail' => '__badUrl__',
'test' =>
'test' =>
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
'type' => 'text'
},
@ -4110,7 +4110,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'SMTPServer' => {
'default' => '',
'test' =>
'test' =>
qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))(?::\d+)?)?$/,
'type' => 'text'
},

View File

@ -77,9 +77,9 @@ sub tree {
form => 'simpleInputContainer',
nodes => [
'portalRequireOldPassword',
'portalEnablePasswordDisplay',
'hideOldPassword',
'mailOnPasswordChange',
'portalEnablePasswordDisplay',
]
},
{

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@ use Exporter 'import';
our $VERSION = '2.0.14';
use constant HANDLER => 'Lemonldap::NG::Handler::PSGI::Main';
use constant URIRE =>
use constant URIRE =>
qr{(((?^:https?))://((?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::((?:[0-9]*)))?(/(((?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?]((?:(?:[;/?:\@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)};
use constant {
PE_IDPCHOICE => -5,

View File

@ -262,18 +262,20 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_USER => $req->{sessionInfo}->{ $self->conf->{portalUserAttr} },
NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow},
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'},
PING => $self->conf->{portalPingInterval},
DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword},
HIDE_OLDPASSWORD => 0,
PPOLICY_NOPOLICY => !$self->isPP(),
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy},
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower},
PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper},
PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit},
PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar},
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'},
PING => $self->conf->{portalPingInterval},
DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword},
HIDE_OLDPASSWORD => 0,
PPOLICY_NOPOLICY => !$self->isPP(),
ENABLE_PASSWORD_DISPLAY =>
$self->conf->{portalEnablePasswordDisplay},
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy},
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower},
PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper},
PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit},
PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar},
(
$self->requireOldPwd->( $req, $req->userData )
? ( REQUIRE_OLDPASSWORD => 1 )
@ -488,6 +490,8 @@ sub display {
HIDE_OLDPASSWORD => $self->conf->{hideOldPassword},
DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword},
PPOLICY_NOPOLICY => !$self->isPP(),
ENABLE_PASSWORD_DISPLAY =>
$self->conf->{portalEnablePasswordDisplay},
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy},
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower},

View File

@ -633,6 +633,8 @@ sub display {
DISPLAY_CONFIRMMAILSENT => 0,
DISPLAY_MAILSENT => 0,
DISPLAY_PASSWORD_FORM => 0,
ENABLE_PASSWORD_DISPLAY => $self->conf->{portalEnablePasswordDisplay},
DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword},
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy} && $isPP,
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower},

View File

@ -491,20 +491,27 @@ $(window).on 'load', () ->
# Functions to show/hide display password button
if datas['enablePasswordDisplay']
field = ''
if datas['dontStorePassword']
$(".toggle-password").mousedown () ->
field = $(this).attr 'id'
field = field.replace /^toggle_/, ''
console.log 'Display', field
$(this).toggleClass("fa-eye fa-eye-slash")
$("input[name=password]").attr('class', 'form-control')
$("input[name=#{field}]").attr('class', 'form-control')
$(".toggle-password").mouseup () ->
$(this).toggleClass("fa-eye fa-eye-slash")
$("input[name=password]").attr('class', 'form-control key') if $("input[name=password]").get(0).value
$("input[name=#{field}]").attr('class', 'form-control key') if $("input[name=#{field}]").get(0).value
else
$(".toggle-password").mousedown () ->
field = $(this).attr 'id'
field = field.replace /^toggle_/, ''
console.log 'Display', field
$(this).toggleClass("fa-eye fa-eye-slash")
$("input[name=password]").attr("type", "text")
$("input[name=#{field}]").attr("type", "text")
$(".toggle-password").mouseup () ->
$(this).toggleClass("fa-eye fa-eye-slash")
$("input[name=password]").attr("type", "password")
$("input[name=#{field}]").attr("type", "password")
# Ping if asked
if datas['pingInterval'] and datas['pingInterval'] > 0
@ -518,31 +525,6 @@ $(window).on 'load', () ->
$('.oidcConsent').on 'click', () ->
removeOidcConsent $(this).attr 'partner'
# Functions to show/hide change password inputs
$('#show-hide-button').on 'click', () ->
if datas['dontStorePassword']
if $("#newpassword").attr('class') == 'form-control key' || $("#confirmpassword").attr('class') == 'form-control key'
console.log 'Show passwords'
$("#newpassword").attr('class', 'form-control')
$("#confirmpassword").attr('class', 'form-control')
$("#show-hide-icon-button").attr('class', 'fa fa-eye-slash')
else
console.log 'Hide passwords'
$("#newpassword").attr('class', 'form-control key') if $("#newpassword").get(0).value
$("#confirmpassword").attr('class', 'form-control key') if $("#confirmpassword").get(0).value
$("#show-hide-icon-button").attr('class', 'fa fa-eye') if ($("#newpassword").get(0).value || $("#confirmpassword").get(0).value)
else
if $("#newpassword").attr('type') == 'password'
console.log 'Show passwords'
$("#newpassword").attr('type', 'text')
$("#confirmpassword").attr('type', 'text')
$("#show-hide-icon-button").attr('class', 'fa fa-eye-slash')
else
console.log 'Hide passwords'
$("#newpassword").attr('type', 'password')
$("#confirmpassword").attr('type', 'password')
$("#show-hide-icon-button").attr('class', 'fa fa-eye')
# Functions to show/hide placeholder password inputs
$('#passwordfield').on 'input', () ->
if $('#passwordfield').get(0).value && datas['dontStorePassword']
@ -556,12 +538,12 @@ $(window).on 'load', () ->
$("#oldpassword").attr('class', 'form-control')
$('#newpassword').on 'input', () ->
if $('#newpassword').get(0).value && datas['dontStorePassword']
$("#newpassword").attr('class', 'form-control key') if $("#show-hide-icon-button").attr('class') == 'fa fa-eye'
$("#newpassword").attr('class', 'form-control key')
else
$("#newpassword").attr('class', 'form-control')
$('#confirmpassword').on 'input', () ->
if $('#confirmpassword').get(0).value && datas['dontStorePassword']
$("#confirmpassword").attr('class', 'form-control key') if $("#show-hide-icon-button").attr('class') == 'fa fa-eye'
$("#confirmpassword").attr('class', 'form-control key')
else
$("#confirmpassword").attr('class', 'form-control')

View File

@ -252,7 +252,7 @@ LemonLDAP::NG Portal jQuery scripts
datas = {};
$(window).on('load', function() {
var action, al, authMenuIndex, authMenuTabs, back_url, checkpassword, checksamepass, hiddenParams, isAlphaNumeric, l, lang, langdiv, langs, langs2, len1, len2, len3, len4, link, m, menuIndex, menuTabs, method, n, nl, nlangs, o, queryLang, re, ref, ref1, ref2, setCookieLang, togglecheckpassword;
var action, al, authMenuIndex, authMenuTabs, back_url, checkpassword, checksamepass, field, hiddenParams, isAlphaNumeric, l, lang, langdiv, langs, langs2, len1, len2, len3, len4, link, m, menuIndex, menuTabs, method, n, nl, nlangs, o, queryLang, re, ref, ref1, ref2, setCookieLang, togglecheckpassword;
datas = getValues();
if ("datas" in window && "choicetab" in window.datas) {
datas.choicetab = window.datas.choicetab;
@ -546,25 +546,34 @@ LemonLDAP::NG Portal jQuery scripts
$('#reset').change(togglecheckpassword);
}
if (datas['enablePasswordDisplay']) {
field = '';
if (datas['dontStorePassword']) {
$(".toggle-password").mousedown(function() {
field = $(this).attr('id');
console.log('Display****', field);
field = field.replace(/^toggle_/, '');
console.log('Display', field);
$(this).toggleClass("fa-eye fa-eye-slash");
return $("input[name=password]").attr('class', 'form-control');
return $("input[name=" + field + "]").attr('class', 'form-control');
});
$(".toggle-password").mouseup(function() {
$(this).toggleClass("fa-eye fa-eye-slash");
if ($("input[name=password]").get(0).value) {
return $("input[name=password]").attr('class', 'form-control key');
if ($("input[name=" + field + "]").get(0).value) {
return $("input[name=" + field + "]").attr('class', 'form-control key');
}
});
} else {
$(".toggle-password").mousedown(function() {
field = $(this).attr('id');
console.log('Display***', field);
field = field.replace(/^toggle_/, '');
console.log('Display', field);
$(this).toggleClass("fa-eye fa-eye-slash");
return $("input[name=password]").attr("type", "text");
return $("input[name=" + field + "]").attr("type", "text");
});
$(".toggle-password").mouseup(function() {
$(this).toggleClass("fa-eye fa-eye-slash");
return $("input[name=password]").attr("type", "password");
return $("input[name=" + field + "]").attr("type", "password");
});
}
}
@ -579,39 +588,6 @@ LemonLDAP::NG Portal jQuery scripts
$('.oidcConsent').on('click', function() {
return removeOidcConsent($(this).attr('partner'));
});
$('#show-hide-button').on('click', function() {
if (datas['dontStorePassword']) {
if ($("#newpassword").attr('class') === 'form-control key' || $("#confirmpassword").attr('class') === 'form-control key') {
console.log('Show passwords');
$("#newpassword").attr('class', 'form-control');
$("#confirmpassword").attr('class', 'form-control');
return $("#show-hide-icon-button").attr('class', 'fa fa-eye-slash');
} else {
console.log('Hide passwords');
if ($("#newpassword").get(0).value) {
$("#newpassword").attr('class', 'form-control key');
}
if ($("#confirmpassword").get(0).value) {
$("#confirmpassword").attr('class', 'form-control key');
}
if ($("#newpassword").get(0).value || $("#confirmpassword").get(0).value) {
return $("#show-hide-icon-button").attr('class', 'fa fa-eye');
}
}
} else {
if ($("#newpassword").attr('type') === 'password') {
console.log('Show passwords');
$("#newpassword").attr('type', 'text');
$("#confirmpassword").attr('type', 'text');
return $("#show-hide-icon-button").attr('class', 'fa fa-eye-slash');
} else {
console.log('Hide passwords');
$("#newpassword").attr('type', 'password');
$("#confirmpassword").attr('type', 'password');
return $("#show-hide-icon-button").attr('class', 'fa fa-eye');
}
}
});
$('#passwordfield').on('input', function() {
if ($('#passwordfield').get(0).value && datas['dontStorePassword']) {
return $("#passwordfield").attr('class', 'form-control key');
@ -628,18 +604,14 @@ LemonLDAP::NG Portal jQuery scripts
});
$('#newpassword').on('input', function() {
if ($('#newpassword').get(0).value && datas['dontStorePassword']) {
if ($("#show-hide-icon-button").attr('class') === 'fa fa-eye') {
return $("#newpassword").attr('class', 'form-control key');
}
return $("#newpassword").attr('class', 'form-control key');
} else {
return $("#newpassword").attr('class', 'form-control');
}
});
$('#confirmpassword').on('input', function() {
if ($('#confirmpassword').get(0).value && datas['dontStorePassword']) {
if ($("#show-hide-icon-button").attr('class') === 'fa fa-eye') {
return $("#confirmpassword").attr('class', 'form-control key');
}
return $("#confirmpassword").attr('class', 'form-control key');
} else {
return $("#confirmpassword").attr('class', 'form-control');
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -120,14 +120,42 @@
<div class="input-group-prepend">
<span class="input-group-text"><label for="newpassword" class="mb-0"><i class="fa fa-lock"></i></label></span>
</div>
<input id="newpassword" name="newpassword" type="password" class="form-control" trplaceholder="newPassword" />
<TMPL_IF NAME="DONT_STORE_PASSWORD">
<input id="newpassword" name="newpassword" type="text" class="form-control" trplaceholder="newPassword" autocomplete="off" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_newpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
<TMPL_ELSE>
<input id="newpassword" name="newpassword" type="password" class="form-control" trplaceholder="newPassword" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_newpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
</TMPL_IF>
</div>
<div class="input-group mb-3">
<div class="form-group input-group">
<div class="input-group-prepend">
<span class="input-group-text"><label for="confirmpassword" class="mb-0"><i class="fa fa-lock"></i></label></span>
</div>
<input id="confirmpassword" name="confirmpassword" type="password" class="form-control" trplaceholder="confirmPwd" />
<TMPL_IF NAME="DONT_STORE_PASSWORD">
<input id="confirmpassword" name="confirmpassword" type="text" class="form-control" trplaceholder="confirmPwd" autocomplete="off" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_confirmpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
<TMPL_ELSE>
<input id="confirmpassword" name="confirmpassword" type="password" class="form-control" trplaceholder="confirmPwd" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_confirmpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
</TMPL_IF>
</div>
<TMPL_IF NAME="DISPLAY_GENERATE_PASSWORD">

View File

@ -35,8 +35,18 @@
</div>
<TMPL_IF NAME="DONT_STORE_PASSWORD">
<input id="oldpassword" name="oldpassword" type="text" value="<TMPL_VAR NAME=OLDPASSWORD>" class="form-control" trplaceholder="currentPwd" autocomplete="off" required aria-required="true">
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_oldpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
<TMPL_ELSE>
<input id="oldpassword" name="oldpassword" type="password" value="<TMPL_VAR NAME=OLDPASSWORD>" class="form-control" trplaceholder="currentPwd" required aria-required="true">
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_oldpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
</TMPL_IF>
</div>
</TMPL_IF>
@ -50,8 +60,18 @@
</div>
<TMPL_IF NAME="DONT_STORE_PASSWORD">
<input id="newpassword" name="newpassword" type="text" class="form-control" trplaceholder="newPassword" autocomplete="off" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_newpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
<TMPL_ELSE>
<input id="newpassword" name="newpassword" type="password" class="form-control" trplaceholder="newPassword" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_newpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
</TMPL_IF>
</div>
<div class="form-group input-group">
@ -60,8 +80,18 @@
</div>
<TMPL_IF NAME="DONT_STORE_PASSWORD">
<input id="confirmpassword" name="confirmpassword" type="text" class="form-control" trplaceholder="confirmPwd" autocomplete="off" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_confirmpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
<TMPL_ELSE>
<input id="confirmpassword" name="confirmpassword" type="password" class="form-control" trplaceholder="confirmPwd" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i id="toggle_confirmpassword" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
</TMPL_IF>
</div>
<div class="buttons">
@ -69,10 +99,6 @@
<span class="fa fa-check-circle"></span>
<span trspan="submit">Submit</span>
</button>
<span id="show-hide-button" class="btn btn-info" role="button">
<span id='show-hide-icon-button' class="fa fa-eye"></span>
<span trspan="showhidePasswords">Show/Hide passwords</span>
</span>
</div>
</div>
</form>

View File

@ -20,14 +20,14 @@
<input id="passwordfield" name="password" type="text" class="form-control" trplaceholder="password" autocomplete="off" required aria-required="true" aria-hidden="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-eye-slash toggle-password"></i></span>
<span class="input-group-text"><i id="toggle_password" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
<TMPL_ELSE>
<input id="passwordfield" name="password" type="password" class="form-control" trplaceholder="password" required aria-required="true"/>
<TMPL_IF NAME="ENABLE_PASSWORD_DISPLAY">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-eye-slash toggle-password"></i></span>
<span class="input-group-text"><i id="toggle_password" class="fa fa-eye-slash toggle-password"></i></span>
</div>
</TMPL_IF>
</TMPL_IF>

View File

@ -1,4 +1,5 @@
use Test::More;
use IO::String;
use strict;
require 't/test-lib.pm';
@ -7,19 +8,64 @@ my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
'portalEnablePasswordDisplay' => 1,
'browsersDontStorePassword' => 1
logLevel => 'error',
portalEnablePasswordDisplay => 1,
browsersDontStorePassword => 1
}
}
);
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Display portal' );
ok( $res->[2]->[0] =~ m%<i class="fa fa-eye-slash toggle-password">%,
' toggle password icon found' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<i id="toggle_password" class="fa fa-eye-slash toggle-password">%,
' toggle password icon found'
) or print STDERR Dumper( $res->[2]->[0] );
count(2);
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23,
),
'Auth query'
);
count(1);
expectOK($res);
my $id = expectCookie($res);
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get menu'
);
ok(
$res->[2]->[0] =~
m%<i id="toggle_oldpassword" class="fa fa-eye-slash toggle-password">%,
' toggle oldpassword icon found'
) or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<i id="toggle_newpassword" class="fa fa-eye-slash toggle-password">%,
' toggle newpassword icon found'
) or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<i id="toggle_confirmpassword" class="fa fa-eye-slash toggle-password">%,
' toggle confirmpassword icon found'
) or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<input id="newpassword" name="newpassword" type="text" class="form-control"%,
' input type text found'
) or print STDERR Dumper( $res->[2]->[0] );
count(5);
$client->logout($id);
clean_sessions();
done_testing( count() );

View File

@ -328,10 +328,10 @@ m%\Q<span trspan="passwordPolicySpecialChar">Allowed special characters:</span>
' passwordPolicySpecialChar'
) or print STDERR Dumper( $res->[2]->[0], 'passwordPolicySpecialChar' );
ok(
$res->[2]->[0] =~
m%<span id=\'show-hide-icon-button\' class="fa fa-eye"></span>%,
'Show/Hide toogle button'
) or print STDERR Dumper( $res->[2]->[0], 'Toogle button' );
$res->[2]->[0] !~
m%class="fa fa-eye-slash toggle-password">%,
' no toggle icon found'
) or print STDERR Dumper( $res->[2]->[0] );
count(8);
# Test $client->logout

View File

@ -13,7 +13,7 @@ BEGIN {
}
my ( $res, $user, $pwd );
my $maintests = 19;
my $maintests = 22;
my $mailSend = 0;
my $mail2 = 0;
@ -54,6 +54,7 @@ SKIP: {
dbiAuthPasswordHash => '',
dbiDynamicHashEnabled => 0,
dbiMailCol => 'mail',
portalEnablePasswordDisplay => 1,
portalDisplayPasswordPolicy => 1,
passwordPolicyActivation => 0,
passwordResetAllowedRetries => 4,
@ -97,7 +98,23 @@ SKIP: {
# Post mismatched passwords
( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' );
ok( $res->[2]->[0] =~ /newpassword/s, ' Ask for a new password #1' );
ok( $res->[2]->[0] =~ /newpassword/s, ' Ask for a new password #1' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<i id="toggle_newpassword" class="fa fa-eye-slash toggle-password">%,
' toggle newpassword icon found'
) or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<i id="toggle_confirmpassword" class="fa fa-eye-slash toggle-password">%,
' toggle confirmpassword icon found'
) or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
m%<input id="newpassword" name="newpassword" type="password" class="form-control"%,
' input type password found'
) or print STDERR Dumper( $res->[2]->[0] );
$query .= '&newpassword=zz&confirmpassword=z';
ok(
@ -129,7 +146,8 @@ SKIP: {
# Post empty password 2
( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' );
ok( $res->[2]->[0] =~ /newpassword/s, ' Ask for a new password #3' );
ok( $res->[2]->[0] =~ /newpassword/s, ' Ask for a new password #3' )
or print STDERR Dumper( $res->[2]->[0] );
$query .= '&newpassword=zz&confirmpassword=';
ok(