From d5a55e7d037e7215aa45cb4c98d802927ecf921b Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Fri, 21 Jun 2019 10:32:55 +0200 Subject: [PATCH] OO-4030: Configuration of username and password in administration GUI --- .../admin/user/ChangeUserPasswordForm.java | 43 +- .../olat/admin/user/UserCreateController.java | 64 ++- .../user/_i18n/LocalStrings_ar.properties | 2 - .../user/_i18n/LocalStrings_bg.properties | 4 +- .../user/_i18n/LocalStrings_cs.properties | 4 +- .../user/_i18n/LocalStrings_da.properties | 4 +- .../user/_i18n/LocalStrings_de.properties | 4 +- .../user/_i18n/LocalStrings_el.properties | 4 +- .../user/_i18n/LocalStrings_en.properties | 4 +- .../user/_i18n/LocalStrings_es.properties | 4 +- .../user/_i18n/LocalStrings_fa.properties | 2 - .../user/_i18n/LocalStrings_fr.properties | 4 +- .../user/_i18n/LocalStrings_it.properties | 4 +- .../user/_i18n/LocalStrings_jp.properties | 2 - .../user/_i18n/LocalStrings_lt.properties | 4 +- .../user/_i18n/LocalStrings_nl_NL.properties | 4 +- .../user/_i18n/LocalStrings_pl.properties | 4 +- .../user/_i18n/LocalStrings_pt_BR.properties | 67 +-- .../user/_i18n/LocalStrings_pt_PT.properties | 76 ---- .../user/_i18n/LocalStrings_ru.properties | 4 +- .../user/_i18n/LocalStrings_sq.properties | 4 +- .../user/_i18n/LocalStrings_zh_CN.properties | 2 - .../user/_i18n/LocalStrings_zh_TW.properties | 2 - .../bulkChange/UserBulkChangeManager.java | 23 +- .../user/bulkChange/UserBulkChangeStep00.java | 25 +- .../_i18n/LocalStrings_ar.properties | 2 +- .../_i18n/LocalStrings_bg.properties | 2 +- .../_i18n/LocalStrings_cs.properties | 2 +- .../_i18n/LocalStrings_de.properties | 10 +- .../_i18n/LocalStrings_el.properties | 2 +- .../_i18n/LocalStrings_en.properties | 2 +- .../_i18n/LocalStrings_es.properties | 2 +- .../_i18n/LocalStrings_fr.properties | 2 +- .../_i18n/LocalStrings_it.properties | 2 +- .../_i18n/LocalStrings_jp.properties | 2 +- .../_i18n/LocalStrings_nl_NL.properties | 2 +- .../_i18n/LocalStrings_pl.properties | 2 +- .../_i18n/LocalStrings_pt_BR.properties | 2 +- .../_i18n/LocalStrings_sq.properties | 2 +- .../_i18n/LocalStrings_zh_CN.properties | 2 +- .../_i18n/LocalStrings_zh_TW.properties | 2 +- .../org/olat/admin/user/imp/ImportStep00.java | 122 ++++-- .../olat/admin/user/imp/_content/step0.html | 11 +- .../user/imp/_i18n/LocalStrings_ar.properties | 2 - .../user/imp/_i18n/LocalStrings_bg.properties | 3 +- .../user/imp/_i18n/LocalStrings_cs.properties | 3 +- .../user/imp/_i18n/LocalStrings_da.properties | 3 +- .../user/imp/_i18n/LocalStrings_de.properties | 10 +- .../user/imp/_i18n/LocalStrings_el.properties | 3 +- .../user/imp/_i18n/LocalStrings_en.properties | 6 +- .../user/imp/_i18n/LocalStrings_es.properties | 3 +- .../user/imp/_i18n/LocalStrings_fa.properties | 9 - .../user/imp/_i18n/LocalStrings_fr.properties | 4 +- .../user/imp/_i18n/LocalStrings_it.properties | 4 +- .../user/imp/_i18n/LocalStrings_jp.properties | 3 +- .../user/imp/_i18n/LocalStrings_lt.properties | 3 +- .../imp/_i18n/LocalStrings_nl_NL.properties | 3 +- .../user/imp/_i18n/LocalStrings_pl.properties | 4 +- .../imp/_i18n/LocalStrings_pt_BR.properties | 4 +- .../imp/_i18n/LocalStrings_pt_PT.properties | 3 +- .../user/imp/_i18n/LocalStrings_ru.properties | 3 +- .../user/imp/_i18n/LocalStrings_sq.properties | 2 - .../imp/_i18n/LocalStrings_zh_CN.properties | 3 +- .../imp/_i18n/LocalStrings_zh_TW.properties | 3 +- .../org/olat/basesecurity/BaseSecurity.java | 4 +- .../basesecurity/BaseSecurityManager.java | 3 +- .../form/flexible/impl/FormItemImpl.java | 2 +- .../flexible/impl/elements/JSDateChooser.java | 2 +- .../CustomfieldsFormController.java | 2 +- .../projectbroker/OptionsFormController.java | 2 +- .../st/EditScoreCalculationEasyForm.java | 2 +- src/main/java/org/olat/login/LoginModule.java | 254 +++++++++++- .../login/_i18n/LocalStrings_de.properties | 68 ++- .../login/_i18n/LocalStrings_en.properties | 59 ++- .../login/_i18n/LocalStrings_fr.properties | 6 +- .../login/_i18n/LocalStrings_pt_BR.properties | 6 +- .../org/olat/login/_spring/loginContext.xml | 4 +- .../org/olat/login/auth/OLATAuthManager.java | 41 +- .../login/auth/OLATAuthentcationForm.java | 2 +- .../oauth/ui/OAuthRegistrationController.java | 36 +- .../org/olat/login/ui/LoginUIFactory.java | 65 +++ .../login/ui/PasswordAdminController.java | 133 ++++++ .../login/ui/PasswordPolicyController.java | 59 +-- .../login/ui/PasswordPreviewController.java | 106 +++++ .../login/ui/PasswordSyntaxController.java | 386 +++++++++++++++++ .../org/olat/login/ui/_content/admin.html | 7 + .../validation/AtLeastCharacterRule.java | 63 +++ .../login/validation/DescriptionRule.java | 41 ++ .../olat/login/validation/HistoryRule.java | 73 ++++ .../IdentityValueForbiddenRule.java | 57 +++ .../olat/login/validation/OppositeRule.java | 54 +++ .../validation/PasswordValidationConfig.java | 192 +++++++++ .../PasswordValidationRuleFactory.java | 192 +++++++++ .../PasswordValidationRulesFactory.java | 178 ++++++++ .../org/olat/login/validation/RegexRule.java | 55 +++ .../login/validation/SyntaxValidator.java | 108 +++++ .../validation/TranslatedDescription.java | 54 +++ .../org/olat/login/validation/TrueRule.java | 46 +++ .../validation/UsernameBlackListRule.java | 49 +++ .../login/validation/UsernameInUseRule.java | 49 +++ .../UsernameValidationRulesFactory.java | 73 ++++ .../validation/ValidationDescription.java | 34 ++ .../login/validation/ValidationResult.java | 36 ++ .../olat/login/validation/ValidationRule.java | 42 ++ .../validation/ValidationRulesProvider.java | 34 ++ .../ValidationRulesProviderBuilder.java | 58 +++ .../org/olat/registration/PwChangeForm.java | 36 +- .../olat/registration/RegistrationForm2.java | 100 +++-- .../_i18n/LocalStrings_de.properties | 3 +- .../_i18n/LocalStrings_en.properties | 1 + .../ShibbolethRegistrationController.java | 4 +- .../ShibbolethRegistrationForm.java | 51 ++- .../olat/user/ChangePasswordController.java | 4 - .../org/olat/user/ChangePasswordForm.java | 102 +++-- src/main/java/org/olat/user/UserManager.java | 29 -- .../UserNameAndPasswordSyntaxChecker.java | 80 ---- ...NameAndPasswordSyntaxCheckerWithEmail.java | 81 ---- ...ameAndPasswordSyntaxCheckerWithRegexp.java | 102 ----- .../olat/user/WebDAVPasswordController.java | 38 +- .../user/_i18n/LocalStrings_ar.properties | 2 - .../user/_i18n/LocalStrings_bg.properties | 3 +- .../user/_i18n/LocalStrings_cs.properties | 3 +- .../user/_i18n/LocalStrings_da.properties | 3 +- .../user/_i18n/LocalStrings_de.properties | 10 +- .../user/_i18n/LocalStrings_el.properties | 3 +- .../user/_i18n/LocalStrings_en.properties | 8 +- .../user/_i18n/LocalStrings_es.properties | 3 +- .../user/_i18n/LocalStrings_fa.properties | 1 - .../user/_i18n/LocalStrings_fr.properties | 4 +- .../user/_i18n/LocalStrings_it.properties | 3 +- .../user/_i18n/LocalStrings_jp.properties | 2 - .../user/_i18n/LocalStrings_lt.properties | 3 +- .../user/_i18n/LocalStrings_nl_NL.properties | 2 - .../user/_i18n/LocalStrings_pl.properties | 3 +- .../user/_i18n/LocalStrings_pt_BR.properties | 4 +- .../user/_i18n/LocalStrings_pt_PT.properties | 3 +- .../user/_i18n/LocalStrings_ru.properties | 3 +- .../user/_i18n/LocalStrings_sq.properties | 3 +- .../user/_i18n/LocalStrings_zh_CN.properties | 2 - .../user/_i18n/LocalStrings_zh_TW.properties | 3 +- .../org/olat/user/_spring/userContext.xml | 11 - .../resources/serviceconfig/olat.properties | 29 ++ .../PasswordSyntaxValidatorTest.java | 138 +++++++ .../PasswordValidationRuleFactoryTest.java | 390 ++++++++++++++++++ .../login/validation/TestingRuleProvider.java | 61 +++ .../java/org/olat/test/AllTestsJunit4.java | 3 +- ...ndPasswordSyntaxCheckerWithRegexpTest.java | 96 ----- 147 files changed, 3719 insertions(+), 1066 deletions(-) create mode 100644 src/main/java/org/olat/login/ui/LoginUIFactory.java create mode 100644 src/main/java/org/olat/login/ui/PasswordAdminController.java create mode 100644 src/main/java/org/olat/login/ui/PasswordPreviewController.java create mode 100644 src/main/java/org/olat/login/ui/PasswordSyntaxController.java create mode 100644 src/main/java/org/olat/login/ui/_content/admin.html create mode 100644 src/main/java/org/olat/login/validation/AtLeastCharacterRule.java create mode 100644 src/main/java/org/olat/login/validation/DescriptionRule.java create mode 100644 src/main/java/org/olat/login/validation/HistoryRule.java create mode 100644 src/main/java/org/olat/login/validation/IdentityValueForbiddenRule.java create mode 100644 src/main/java/org/olat/login/validation/OppositeRule.java create mode 100644 src/main/java/org/olat/login/validation/PasswordValidationConfig.java create mode 100644 src/main/java/org/olat/login/validation/PasswordValidationRuleFactory.java create mode 100644 src/main/java/org/olat/login/validation/PasswordValidationRulesFactory.java create mode 100644 src/main/java/org/olat/login/validation/RegexRule.java create mode 100644 src/main/java/org/olat/login/validation/SyntaxValidator.java create mode 100644 src/main/java/org/olat/login/validation/TranslatedDescription.java create mode 100644 src/main/java/org/olat/login/validation/TrueRule.java create mode 100644 src/main/java/org/olat/login/validation/UsernameBlackListRule.java create mode 100644 src/main/java/org/olat/login/validation/UsernameInUseRule.java create mode 100644 src/main/java/org/olat/login/validation/UsernameValidationRulesFactory.java create mode 100644 src/main/java/org/olat/login/validation/ValidationDescription.java create mode 100644 src/main/java/org/olat/login/validation/ValidationResult.java create mode 100644 src/main/java/org/olat/login/validation/ValidationRule.java create mode 100644 src/main/java/org/olat/login/validation/ValidationRulesProvider.java create mode 100644 src/main/java/org/olat/login/validation/ValidationRulesProviderBuilder.java delete mode 100644 src/main/java/org/olat/user/UserNameAndPasswordSyntaxChecker.java delete mode 100644 src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithEmail.java delete mode 100644 src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexp.java create mode 100644 src/test/java/org/olat/login/validation/PasswordSyntaxValidatorTest.java create mode 100644 src/test/java/org/olat/login/validation/PasswordValidationRuleFactoryTest.java create mode 100644 src/test/java/org/olat/login/validation/TestingRuleProvider.java delete mode 100644 src/test/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexpTest.java diff --git a/src/main/java/org/olat/admin/user/ChangeUserPasswordForm.java b/src/main/java/org/olat/admin/user/ChangeUserPasswordForm.java index ce524351f2c..28cf0a00c9c 100644 --- a/src/main/java/org/olat/admin/user/ChangeUserPasswordForm.java +++ b/src/main/java/org/olat/admin/user/ChangeUserPasswordForm.java @@ -25,6 +25,8 @@ package org.olat.admin.user; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.TextElement; @@ -34,8 +36,10 @@ import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.core.util.Util; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.user.ChangePasswordForm; -import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; /** @@ -52,10 +56,11 @@ public class ChangeUserPasswordForm extends FormBasicController { private String cred = ""; - private Identity userIdentity; + private final SyntaxValidator syntaxValidator; + private final Identity userIdentity; @Autowired - private UserManager userManager; + private OLATAuthManager olatAuthManager; /** * Constructor for user pwd forms. @@ -67,24 +72,30 @@ public class ChangeUserPasswordForm extends FormBasicController { public ChangeUserPasswordForm(UserRequest ureq, WindowControl wControl, Identity treatedIdentity) { super(ureq, wControl, null, Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale())); userIdentity = treatedIdentity; + this.syntaxValidator = olatAuthManager.createPasswordSytaxValidator(); initForm(ureq); } @Override public boolean validateFormLogic (UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); - boolean newIsValid = userManager.syntaxCheckOlatPassword(pass1.getValue()); - if (!newIsValid) pass1.setErrorKey("form.checkPassword", null); - - boolean newDoesMatch = pass1.getValue().equals(pass2.getValue()); - if(!newDoesMatch) pass1.setErrorKey("error.password.nomatch", null); - - if (newIsValid && newDoesMatch) return true; - - pass1.setValue(""); - pass2.setValue(""); + pass1.clearError(); + String newPassword = pass1.getValue(); + ValidationResult validationResult = syntaxValidator.validate(newPassword, userIdentity); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + pass1.setErrorKey("error.password.invalid", new String[] { descriptions }); + allOk &= false; + } + + pass2.clearError(); + if (!pass1.getValue().equals(pass2.getValue())) { + pass2.setErrorKey("error.password.nomatch", null); + allOk &= false; + } - return false; + return allOk; } @Override @@ -102,7 +113,9 @@ public class ChangeUserPasswordForm extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { setFormTitle("form.password.new1"); - setFormDescription("form.please.enter.new"); + + String descriptions = formatDescriptionAsList(syntaxValidator.getAllDescriptions(), getLocale()); + setFormDescription("form.please.enter.new", new String[] { descriptions }); TextElement username = uifactory.addTextElement("username", "form.username", 255, userIdentity.getName(), formLayout); username.setEnabled(false); diff --git a/src/main/java/org/olat/admin/user/UserCreateController.java b/src/main/java/org/olat/admin/user/UserCreateController.java index 45a22565e35..5e068781118 100644 --- a/src/main/java/org/olat/admin/user/UserCreateController.java +++ b/src/main/java/org/olat/admin/user/UserCreateController.java @@ -25,10 +25,14 @@ package org.olat.admin.user; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.apache.logging.log4j.Logger; +import org.olat.admin.user.imp.TransientIdentity; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.OrganisationRoles; import org.olat.basesecurity.OrganisationService; @@ -54,13 +58,16 @@ import org.olat.core.id.Organisation; import org.olat.core.id.Roles; import org.olat.core.id.User; import org.olat.core.id.UserConstants; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.ArrayHelper; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; +import org.olat.login.LoginModule; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.registration.RegistrationManager; import org.olat.registration.TemporaryKey; import org.olat.user.ChangePasswordForm; @@ -157,6 +164,8 @@ class NewUserForm extends FormBasicController { private DialogBoxController confirmRemoveCtrl; + private final SyntaxValidator passwordSyntaxValidator; + private final SyntaxValidator usernameSyntaxValidator; @Autowired private UserModule userModule; @@ -165,6 +174,8 @@ class NewUserForm extends FormBasicController { @Autowired private BaseSecurity securityManager; @Autowired + private OLATAuthManager olatAuthManager; + @Autowired private RegistrationManager registrationManager; @Autowired private OrganisationService organisationService; @@ -178,8 +189,11 @@ class NewUserForm extends FormBasicController { */ public NewUserForm(UserRequest ureq, WindowControl wControl, boolean showPasswordFields, Translator translator) { super(ureq, wControl); - setTranslator(translator); + setTranslator(Util.createPackageTranslator(LoginModule.class, ureq.getLocale(), translator)); + setTranslator(Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale(), getTranslator())); this.showPasswordFields = showPasswordFields; + this.passwordSyntaxValidator = olatAuthManager.createPasswordSytaxValidator(); + this.usernameSyntaxValidator = olatAuthManager.createUsernameSytaxValidator(); Roles managerRoles = ureq.getUserSession().getRoles(); if(managerRoles.isSystemAdmin()) { @@ -243,7 +257,9 @@ class NewUserForm extends FormBasicController { //add password fields!!! if (showPasswordFields) { - uifactory.addStaticTextElement("heading2", null, translate("new.form.please.enter.pwd"), formLayout); + String descriptions = formatDescriptionAsList(passwordSyntaxValidator.getAllDescriptions(), getLocale()); + uifactory.addStaticTextElement("heading2", null, + translate("new.form.please.enter.pwd", new String[] { descriptions }), formLayout); // checkBox: generate user with OLAT authentication or not String[] authKeys = {"xx"}; @@ -253,14 +269,14 @@ class NewUserForm extends FormBasicController { authCheckbox.addActionListener(FormEvent.ONCLICK); // if OLAT authentication is used, use the pwd below - psw1TextElement = uifactory.addPasswordElement(FIELD_NEW1, "new.form.password.new1", 255, "", formLayout); + psw1TextElement = uifactory.addPasswordElement(FIELD_NEW1, "new.form.password.new1", 5000, "", formLayout); psw1TextElement.setMandatory(true); psw1TextElement.setDisplaySize(30); psw1TextElement.setVisible(showPasswordFields); psw1TextElement.setElementCssClass("o_sel_id_password1"); psw1TextElement.setAutocomplete("new-password"); - psw2TextElement = uifactory.addPasswordElement(FIELD_NEW2, "new.form.password.new2", 255, "", formLayout); + psw2TextElement = uifactory.addPasswordElement(FIELD_NEW2, "new.form.password.new2", 5000, "", formLayout); psw2TextElement.setMandatory(true); psw2TextElement.setDisplaySize(30); psw2TextElement.setVisible(showPasswordFields); @@ -295,21 +311,29 @@ class NewUserForm extends FormBasicController { protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = super.validateFormLogic(ureq); + // Transient identity for validations + String username = usernameTextElement.getValue(); + TransientIdentity newIdentity = new TransientIdentity(); + newIdentity.setName(username); + for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { + FormItem propertyItem = flc.getFormComponent(userPropertyHandler.getName()); + newIdentity.setProperty(userPropertyHandler.getName(), userPropertyHandler.getStringValue(propertyItem)); + } + // validate if username does match the syntactical login requirements - String loginName = usernameTextElement.getValue(); usernameTextElement.clearError(); - if (usernameTextElement.isEmpty() || !userManager.syntaxCheckOlatLogin(loginName)) { - usernameTextElement.setErrorKey("new.error.loginname.empty", new String[]{}); + if (!StringHelper.containsNonWhitespace(username)) { + usernameTextElement.setErrorKey("form.legende.mandatory", null); allOk &= false; } else { - // Check if login is still available - Identity identity = securityManager.findIdentityByName(loginName); - if (identity != null) { - usernameTextElement.setErrorKey("new.error.loginname.choosen", new String[]{}); + ValidationResult validationResult = usernameSyntaxValidator.validate(username, newIdentity); + if (!validationResult.isValid()) { + String descriptions = validationResult.getInvalidDescriptions().get(0).getText(getLocale()); + usernameTextElement.setErrorKey("error.username.invalid", new String[] { descriptions }); allOk &= false; } } - + // validate special rules for each user property for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { //we assume here that there are only textElements for the user properties @@ -347,9 +371,15 @@ class NewUserForm extends FormBasicController { String pwd = psw1TextElement.getValue(); if(psw1TextElement.isEmpty("new.form.mandatory") || psw1TextElement.hasError()) { allOk &= false; - } else if (!userManager.syntaxCheckOlatPassword(pwd)) { - psw1TextElement.setErrorKey("form.checkPassword", new String[]{}); - allOk &= false; + } else { + String newPassword = psw1TextElement.getValue(); + + ValidationResult validationResult = passwordSyntaxValidator.validate(newPassword, newIdentity); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + psw1TextElement.setErrorKey("error.password.invalid", new String[] { descriptions }); + allOk &= false; + } } if(psw2TextElement.isEmpty("new.form.mandatory") || psw2TextElement.hasError()) { allOk &= false; @@ -377,7 +407,7 @@ class NewUserForm extends FormBasicController { @Override protected void formResetted(UserRequest ureq) { - fireEvent(ureq, Event.CANCELLED_EVENT); + fireEvent(ureq, Event.CANCELLED_EVENT); } private Identity doCreateAndPersistIdentity() { diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ar.properties index 82909240d0a..1b848d62f41 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ar.properties @@ -34,7 +34,6 @@ error.search.form.notempty=\u064A\u0631\u062C\u0649 \u0627\u0644\u0643\u062A\u06 error.search.form.to.short=\u0643\u0644\u0645\u0629 \u0627\u0644\u0628\u062D\u062B \u0642\u0635\u064A\u0631\u0629 \u062C\u062F\u0627\u064B form.password.new1=\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 \u0627\u0644\u062C\u062F\u064A\u062F\u0629 form.password.new2=\u062A\u0623\u0643\u064A\u062F \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 -form.please.enter.new=\u064A\u0631\u062C\u0649 \u0625\u062F\u062E\u0644 \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 \u0627\u0644\u062C\u062F\u064A\u062F\u0629 \u0644\u0647\u0630\u0627 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 form.token.new.text=\u0631\u0633\u0627\u0644\u0629 form.token.new.title=\u0625\u0631\u0633\u0627\u0644 \u0631\u0627\u0628\u0637 \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 form.username=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 @@ -56,7 +55,6 @@ new.form.mandatory=\u0647\u0630\u0647 \u0627\u0644\u062E\u0644\u064A\u0629 \u063 new.form.password.new1=\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 new.form.password.new2=\u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 new.form.please.enter=\u064A\u0631\u062C\u0649 \u0625\u062F\u062E\u0627\u0644 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0627\u0644\u062A\u0627\u0644\u064A\u0629 \u0639\u0646 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 \u0627\u0644\u062C\u062F\u064A\u062F -new.form.please.enter.pwd=\u0627\u062E\u062A\u064A\u0627\u0631 \u0643\u0644\u0645\u0629 \u0645\u0631\u0648\u0631 \u0644\u0644\u0645\u0633\u062A\u062E\u062F\u0645 \u0627\u0644\u062C\u062F\u064A\u062F new.form.username=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 new.user.cancel=\u062A\u0645 \u0625\u0644\u063A\u0627\u0621 \u0627\u0644\u0646\u0634\u0627\u0637\u060C \u0644\u0645 \u064A\u062A\u0645 \u0625\u0646\u0634\u0627\u0621 \u062D\u0633\u0627\u0628 \u0645\u0633\u062A\u062E\u062F\u0645 \u062C\u062F\u064A\u062F. new.user.successful=\u062A\u0645 \u0625\u0646\u0634\u0627\u0621 \u062D\u0633\u0627\u0628 \u0645\u0633\u062A\u062E\u062F\u0645 \u062C\u062F\u064A\u062F \u0628\u0646\u062C\u0627\u062D. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_bg.properties index f8e354835a5..aa40adcc695 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_bg.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_bg.properties @@ -32,7 +32,7 @@ error.password.nomatch=\u0414\u0432\u0435\u0442\u0435 \u043D\u043E\u0432\u0438 \ error.search.form.notempty=\u041C\u043E\u043B\u044F, \u043F\u043E\u043F\u044A\u043B\u043D\u0435\u0442\u0435 \u043F\u043E\u043D\u0435 \u0435\u0434\u043D\u043E \u043E\u0442 \u0441\u044A\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0438\u0442\u0435 \u043F\u043E\u043B\u0435\u0442\u0430. form.password.new1=\u041D\u043E\u0432\u0430 \u043F\u0430\u0440\u043E\u043B\u0430 form.password.new2=\u041F\u043E\u0442\u0432\u044A\u0440\u0434\u0435\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u0430 -form.please.enter.new=\u041C\u043E\u043B\u044F, \u043D\u0430\u043F\u0438\u0448\u0435\u0442\u0435 \u043D\u043E\u0432\u0430 \u043F\u0430\u0440\u043E\u043B\u0430 \u0437\u0430 \u0442\u043E\u0437\u0438 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B +form.please.enter.new=\u041C\u043E\u043B\u044F, \u043D\u0430\u043F\u0438\u0448\u0435\u0442\u0435 \u043D\u043E\u0432\u0430 \u043F\u0430\u0440\u043E\u043B\u0430 \u0437\u0430 \u0442\u043E\u0437\u0438 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B.{0} form.username=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435 found.property=\u0418\u0437\u0431\u0440\u0430\u043D\u0430 \u0445\u0430\u0440\u0430\u043A\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043A\u0430 {0} header.autocompletion=\u0422\u044A\u0440\u0441\u0435\u0442\u0435 \u0432 \u043A\u043E\u043C\u0431\u0438\u043D\u0430\u0446\u0438\u044F \u0441 \u0430\u0432\u0442\u043E-\u043F\u043E\u043F\u044A\u043B\u0432\u0430\u043D\u0435 @@ -52,7 +52,7 @@ new.form.mandatory=\u0422\u043E\u0432\u0430 \u0435 \u0437\u0430\u0434\u044A\u043 new.form.password.new1=\u041F\u0430\u0440\u043E\u043B\u0430 new.form.password.new2=\u041F\u043E\u0442\u0432\u044A\u0440\u0434\u0435\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u0430 new.form.please.enter=\u041C\u043E\u043B\u044F, \u043D\u0430\u043F\u0438\u0448\u0435\u0442\u0435 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u0437\u0430 \u043D\u043E\u0432 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B -new.form.please.enter.pwd=\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u0430 \u0437\u0430 \u043D\u043E\u0432 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B +new.form.please.enter.pwd=\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u0430 \u0437\u0430 \u043D\u043E\u0432 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B.{0} new.form.username=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435 new.user.cancel=\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F\u0442\u0430 \u0435 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u0430. \u041D\u0435 \u0435 \u0441\u044A\u0437\u0434\u0430\u0434\u0435\u043D \u043D\u043E\u0432 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u0438 \u0430\u043A\u0430\u0443\u043D\u0442. new.user.successful=\u041D\u043E\u0432\u0438\u044F\u0442 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u0438 \u0430\u043A\u0430\u0443\u043D\u0442 \u0435 \u0441\u044A\u0437\u0434\u0430\u0434\u0435\u043D \u0443\u0441\u043F\u0435\u0448\u043D\u043E. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_cs.properties index 4c79abb4f3c..cb15c20ad5e 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_cs.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_cs.properties @@ -29,7 +29,7 @@ error.password.nomatch=Vlo\u017Een\u00E1 hesla nejsou toto\u017En\u00E1. error.search.form.notempty=Pros\u00EDm, vypl\u0148te alespo\u0148 jedno z dostupn\u00FDch pol\u00ED. form.password.new1=Nov\u00E9 heslo form.password.new2=Potvrdit heslo -form.please.enter.new=Pros\u00EDm vlo\u017Ete nov\u00E9 heslo u\u017Eivatele +form.please.enter.new=Pros\u00EDm vlo\u017Ete nov\u00E9 heslo u\u017Eivatele.{0} form.username=U\u017Eivatelsk\u00E9 jm\u00E9no found.property=Vybran\u00FD parametr {0} header.autocompletion=Vyhled\u00E1v\u00E1n\u00ED kombinovan\u00E9 s automatick\u00FDm dokon\u010Dov\u00E1n\u00EDm @@ -49,7 +49,7 @@ new.form.mandatory=Toto pole je povinn\u00E9, vlo\u017Ete pros\u00EDm hodnotu\! new.form.password.new1=Heslo new.form.password.new2=Ov\u011B\u0159en\u00ED hesla new.form.please.enter=Pros\u00EDm vlo\u017Ete informace o nov\u00E9m u\u017Eivateli -new.form.please.enter.pwd=Vyberte pro nov\u00E9ho u\u017Eivatele heslo +new.form.please.enter.pwd=Vyberte pro nov\u00E9ho u\u017Eivatele heslo.{0} new.form.username=U\u017Eivatelsk\u00E9 jm\u00E9no new.user.cancel=Akce byla zru\u0161ena. Nov\u00FD \u00FA\u010Det nebyl vytvo\u0159en. new.user.successful=Nov\u00FD u\u017Eivatelsk\u00FD \u00FA\u010Det byl \u00FAsp\u011B\u0161n\u011B vytvo\u0159en. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_da.properties index 38a43c836b0..251281f2a05 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_da.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_da.properties @@ -24,7 +24,7 @@ error.password.nomatch=De indtastede kodeord passer ikke sammen. error.search.form.notempty=Udfyld venligst et af de tilg\u00E6ngelige felter form.password.new1=Nyt kodeord form.password.new2=Bekr\u00E6ft kodeord -form.please.enter.new=Indtast venligst et nyt kodeord for denne bruger +form.please.enter.new=Indtast venligst et nyt kodeord for denne bruger.{0} form.username=Brugernavn found.property=Egenskab valgt {0} header.autocompletion=S\u00F8gning kombineret med auto-completion @@ -41,7 +41,7 @@ new.form.language=Sprog new.form.password.new1=Kodeord new.form.password.new2=Bekr\u00E6ft kodeord new.form.please.enter=Indtast venligst information om den nye bruger -new.form.please.enter.pwd=V\u00E6lg et kodeord for den nye bruger +new.form.please.enter.pwd=V\u00E6lg et kodeord for den nye bruger.{0} new.form.username=Brugernavn new.user.cancel=Handlingen er afbrudt. Ingen ny konto er oprettet. new.user.successful=Den nye brugerkonto er oprettet succesfult. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties index 823b0f9907e..d8d4779799b 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties @@ -53,7 +53,7 @@ export.user.data=Daten exportieren export.user.data.title=Benutzerdaten von "{0}" exportieren form.password.new1=Neues Passwort form.password.new2=Passwort best\u00E4tigen -form.please.enter.new=Bitte geben Sie das neue Passwort f\u00FCr diesen Benutzer ein. +form.please.enter.new=Bitte geben Sie das neue Passwort f\u00FCr diesen Benutzer ein.{0} form.token.new.description=Mit Hilfe der Schaltfl\u00E4che "Passwortlink senden" erstellen Sie einen Passwortlink und senden diesen direkt per Mail an den Benutzer. Mit einem Klick darauf wird das alte Passwort zur\u00FCckgesetzt und der Benutzer kann ein neues Passwort eingeben. form.token.new.text=Nachricht form.token.new.title=Passwortlink senden f\u00FCr OpenOLAT Passwort @@ -81,7 +81,7 @@ new.form.organisations=Organisation new.form.password.new1=Passwort new.form.password.new2=Passwort verifizieren new.form.please.enter=Angaben zur Person des neuen Benutzerkontos -new.form.please.enter.pwd=Setzen Sie dem Benutzer ein Passwort. +new.form.please.enter.pwd=Setzen Sie dem Benutzer ein Passwort.{0} new.form.username=Benutzername new.user.cancel=Die Aktion wurde abgebrochen. Es wurde keine neues Benutzerkonto angelegt. new.user.successful=Das neue Benutzerkonto wurde angelegt. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_el.properties index 699e4158fe2..c76defe04a8 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_el.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_el.properties @@ -35,7 +35,7 @@ error.search.form.notempty=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03C error.search.form.to.short=\u03A0\u03BF\u03BB\u03CD \u03BC\u03B9\u03BA\u03C1\u03CC\u03C2 \u03CC\u03C1\u03BF\u03C2 \u03B1\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7\u03C2. form.password.new1=\u039D\u03AD\u03BF\u03C2 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 form.password.new2=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 -form.please.enter.new=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03CD\u03BC\u03B5 \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03BD\u03AD\u03BF \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03BF \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 +form.please.enter.new=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03CD\u03BC\u03B5 \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03BD\u03AD\u03BF \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03BF \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7.{0} form.token.new.text=\u039C\u03AE\u03BD\u03C5\u03BC\u03B1 form.username=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 found.property=\u0397 \u03B9\u03B4\u03B9\u03CC\u03C4\u03B7\u03C4\u03B1 \u03B5\u03C0\u03B9\u03BB\u03AD\u03C7\u03C4\u03B7\u03BA\u03B5 @@ -56,7 +56,7 @@ new.form.mandatory=\u03A4\u03BF \u03C0\u03B5\u03B4\u03AF\u03BF \u03B5\u03AF\u03B new.form.password.new1=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 new.form.password.new2=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD new.form.please.enter=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03C4\u03B9\u03C2 \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03AF\u03B5\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03BF \u03BD\u03AD\u03BF \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 -new.form.please.enter.pwd=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03BF \u03BD\u03AD\u03BF \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 +new.form.please.enter.pwd=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03BF \u03BD\u03AD\u03BF \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7.{0} new.form.username=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 new.user.cancel=\u0397 \u03B5\u03BD\u03AD\u03C1\u03B3\u03B5\u03B9\u03B1 \u03B1\u03BA\u03C5\u03C1\u03CE\u03B8\u03B7\u03BA\u03B5. \u039F \u03BD\u03AD\u03BF\u03C2 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7\u03C2 \u03B4\u03B5\u03BD \u03B4\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03AE\u03B8\u03B7\u03BA\u03B5. new.user.successful=\u039F \u03BD\u03AD\u03BF\u03C2 \u03BB\u03BF\u03B3\u03B1\u03C1\u03B9\u03B1\u03C3\u03BC\u03CC\u03C2 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03B4\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03AE\u03B8\u03B7\u03BA\u03B5 \u03BC\u03B5 \u03B5\u03C0\u03B9\u03C4\u03C5\u03C7\u03AF\u03B1. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties index 2772dd8d09b..d2a085a9226 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties @@ -53,7 +53,7 @@ export.user.data=Export data export.user.data.title=Export user data of "{0}" form.password.new1=New password form.password.new2=Confirm password -form.please.enter.new=Please enter a new password for this user +form.please.enter.new=Please enter a new password for this user.{0} form.token.new.description=By means of the button "Send password link" you can create a password link and send it via e-mail to your user. When clicking on it an old password will be reset allowing your user to set a new one. form.token.new.text=Message form.token.new.title=Send password link for OpenOLAT password @@ -81,7 +81,7 @@ new.form.organisations=Organisation new.form.password.new1=Password new.form.password.new2=Verify password new.form.please.enter=Please enter information on new user -new.form.please.enter.pwd=Choose a password for new user +new.form.please.enter.pwd=Choose a password for the new user.{0} new.form.username=User name new.user.cancel=Action cancelled. No new user account created. new.user.successful=The new user account has been created successfully. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_es.properties index 492ad7fa2a8..20b20a480cb 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_es.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_es.properties @@ -30,7 +30,7 @@ error.password.nomatch=Las dos nuevas contrase\u00F1as no coinciden. error.search.form.notempty=Por favor rellena al menos una de las casillas disponibles. form.password.new1=Nueva contrase\u00F1a form.password.new2=Confirmar contrase\u00F1a -form.please.enter.new=Por favor introduce la nueva contrase\u00F1a para este usuario +form.please.enter.new=Por favor introduce la nueva contrase\u00F1a para este usuario.{0} form.username=Nombre de usuario found.property=Propiedad seleccionada {0} header.autocompletion=Buscar con auto-completamiento @@ -50,7 +50,7 @@ new.form.mandatory=\u00A1Esta es una casilla requerida, por favor introduzca un new.form.password.new1=Contrase\u00F1a new.form.password.new2=Confirmar contrase\u00F1a new.form.please.enter=Por favor introduce la informaci\u00F3n del nuevo usuario -new.form.please.enter.pwd=Selecciona una contrase\u00F1a para el nuevo usuario +new.form.please.enter.pwd=Selecciona una contrase\u00F1a para el nuevo usuario.{0} new.form.username=Nombre de usuario new.user.cancel=Acci\u00F3n cancelada. No se cre\u00F3 la nueva cuenta de usuario. new.user.successful=La nueva cuenta de usuario se cre\u00F3 correctamente. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fa.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fa.properties index 970405f3153..f17cfbb4e92 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fa.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fa.properties @@ -23,7 +23,6 @@ error.password.nomatch=\u062F\u0648 \u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\ error.search.form.notempty=\u0644\u0637\u0641\u0627\u064B \u062D\u062F\u0627\u0642\u0644 \u06CC\u06A9\u06CC \u0627\u0632 \u0641\u06CC\u0644\u062F\u0647\u0627 \u0631\u0627 \u067E\u0631 \u06A9\u0646 form.password.new1=\u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 \u062C\u062F\u06CC\u062F form.password.new2=\u062A\u0627\u06CC\u06CC\u062F \u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 -form.please.enter.new=\u0644\u0637\u0641\u0627\u064B \u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 \u062C\u062F\u06CC\u062F \u0628\u0631\u0627\u06CC \u0627\u06CC\u0646 \u06A9\u0627\u0631\u0628\u0631 \u0627\u0646\u062A\u062E\u0627\u0628 \u0646\u0645\u0627\u06CC\u06CC\u062F form.username=\u0646\u0627\u0645 \u06A9\u0627\u0631\u0628\u0631 found.property=\u0645\u0634\u062E\u0635\u0647 \u0627\u0646\u062A\u062E\u0627\u0628 \u0634\u062F mailto.userlist=\u0644\u06CC\u0633\u062A \u06A9\u0627\u0631\u0628\u0631\u0627\u0646 @@ -38,7 +37,6 @@ new.form.language=\u0632\u0628\u0627\u0646 new.form.password.new1=\u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 new.form.password.new2=\u0634\u0646\u0627\u0633\u0627\u06CC\u06CC \u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 new.form.please.enter=\u0644\u0637\u0641\u0627\u064B \u0627\u0637\u0644\u0627\u0639\u0627\u062A \u06A9\u0627\u0631\u0628\u0631 \u062C\u062F\u06CC\u062F \u0631\u0627 \u0648\u0627\u0631\u062F \u0646\u0645\u0627\u06CC\u06CC\u062F -new.form.please.enter.pwd=\u0627\u0646\u062A\u062E\u0627\u0628 \u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 \u0628\u0631\u0627\u06CC \u06A9\u0627\u0631\u0628\u0631 \u062C\u062F\u06CC\u062F new.form.username=\u0646\u0627\u0645 \u06A9\u0627\u0631\u0628\u0631 new.user.cancel=\u0639\u0645\u0644\u06CC\u0627\u062A \u0644\u063A\u0648 \u06AF\u0631\u062F\u06CC\u062F / \u0647\u06CC\u0686 \u06A9\u0627\u0631\u0628\u0631\u06CC \u0627\u06CC\u062C\u0627\u062F \u0646\u06AF\u0631\u062F\u06CC\u062F new.user.successful=\u062D\u0633\u0627\u0628 \u06A9\u0627\u0631\u0628\u0631 \u062C\u062F\u06CC\u062F \u0628\u0627 \u0645\u0648\u0641\u0642\u06CC\u062A \u0627\u06CC\u062C\u0627\u062F \u06AF\u0631\u062F\u06CC\u062F diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fr.properties index a59027cedfd..3c40c864aa7 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_fr.properties @@ -53,7 +53,7 @@ export.user.data=Exporter les donn\u00E9es export.user.data.title=Exporter les donn\u00E9es utilisateurs de "{0}" form.password.new1=Nouveau mot de passe form.password.new2=Confirmer mot de passe -form.please.enter.new=Veuillez ins\u00E9rer le nouveaux mot de passe pour cet utilisateur s.v.p. +form.please.enter.new=Veuillez ins\u00E9rer le nouveaux mot de passe pour cet utilisateur s.v.p.{0} form.token.new.description=Gr\u00E2ce au bouton "Envoyer lien mot de passe", vous pouvez cr\u00E9er un lien pour le mot de passe et l'envoyer \u00E0 l'utilisateur par e-mail. En cliquant dessus, l'utilisateur peut introduire un nouveau mot de passe (l'ancien mot de passe sera annul\u00E9). form.token.new.text=Message form.token.new.title=Envoyer lien mot de passe @@ -81,7 +81,7 @@ new.form.organisations=Organisation new.form.password.new1=Mot de passe new.form.password.new2=V\u00E9rifier mot de passe new.form.please.enter=Informations sur la personne du nouveau compte utilisateur -new.form.please.enter.pwd=Attribuez un mot de passe \u00E0 l'utilisateur +new.form.please.enter.pwd=Attribuez un mot de passe \u00E0 l'utilisateur.{0} new.form.username=Nom d'utilisateur new.user.cancel=L'action a \u00E9t\u00E9 annul\u00E9e. Aucun nouveau compte utilisateur n'a \u00E9t\u00E9 cr\u00E9\u00E9. new.user.successful=Le nouveau compte utilisateur a \u00E9t\u00E9 cr\u00E9\u00E9. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_it.properties index 167ac1b5a81..2475d12b389 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_it.properties @@ -40,7 +40,7 @@ error.search.form.to.short=Termine di ricerca troppo corto. error.search.maxResults=Troppi risultati trovati. Solo i primi {0} risultati sono mostrati. form.password.new1=Nuova password form.password.new2=Conferma la password -form.please.enter.new=Inserisca la nuova password per questo utente, p.f. +form.please.enter.new=Inserisca la nuova password per questo utente, p.f.{0} form.token.new.description=Mediante il pulsante "Inviare link password" pu\u00F2 creare un link per la password e inviarlo all'utente via e-mail. Cliccandolo, l'utente pu\u00F2 immettere una nuova password (la vecchia password viene annullata). form.token.new.text=Messaggio form.token.new.title=Inviare link password @@ -65,7 +65,7 @@ new.form.mandatory=Questa \u00E8 una casella obbligatoria, inserisca un valore, new.form.password.new1=Password new.form.password.new2=Conferma la password new.form.please.enter=Indicazioni sulla persona relativa al nuovo conto utente -new.form.please.enter.pwd=Stabilisca una password per l'utente. +new.form.please.enter.pwd=Stabilisca una password per l'utente.{0} new.form.username=Nome utente new.user.cancel=L'azione \u00E8 stata interrotta. Nessun nuovo conto utente \u00E8 stato creato. new.user.successful=Il nuovo conto utente \u00E8 stato creato. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_jp.properties index f3cba975419..b3ba2e649f0 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_jp.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_jp.properties @@ -36,7 +36,6 @@ error.search.form.notempty=\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u6709\u52 error.search.form.to.short=\u691C\u7D22\u30AD\u30FC\u30EF\u30FC\u30C9\u304C\u77ED\u3059\u304E\u307E\u3059\u3002 form.password.new1=\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9 form.password.new2=\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u3082\u3046\u4E00\u5EA6 -form.please.enter.new=\u3053\u306E\u30E6\u30FC\u30B6\u306E\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 form.token.new.text=\u30E1\u30C3\u30BB\u30FC\u30B8 form.token.new.title=\u30D1\u30B9\u30EF\u30FC\u30C9\u30EA\u30F3\u30AF\u3092\u9001\u4FE1\u3059\u308B form.username=\u30E6\u30FC\u30B6\u540D @@ -58,7 +57,6 @@ new.form.mandatory=\u3053\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u3001\u5FC5\ new.form.password.new1=\u30D1\u30B9\u30EF\u30FC\u30C9 new.form.password.new2=\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u3082\u3046\u4E00\u5EA6 new.form.please.enter=\u65B0\u3057\u3044\u30E6\u30FC\u30B6\u306E\u60C5\u5831\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 -new.form.please.enter.pwd=\u65B0\u3057\u3044\u30E6\u30FC\u30B6\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002 new.form.username=\u30E6\u30FC\u30B6\u540D new.user.cancel=\u51E6\u7406\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002\u65B0\u3057\u3044\u30E6\u30FC\u30B6\u306F\u3001\u4F5C\u6210\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002 new.user.successful=\u65B0\u3057\u3044\u30E6\u30FC\u30B6\u30A2\u30AB\u30A6\u30F3\u30C8\u304C\u6B63\u5E38\u306B\u4F5C\u6210\u3055\u308C\u307E\u3057\u305F\u3002 diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_lt.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_lt.properties index d546e5659de..224f6ac414e 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_lt.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_lt.properties @@ -23,7 +23,7 @@ error.password.nomatch=Slapta\u017Eod\u017Eiai nesutampa. error.search.form.notempty=Pra\u0161ome u\u017Epildyti bent vien\u0105 lauk\u0105. form.password.new1=Naujas slapta\u017Eodis form.password.new2=Pakartoti slapta\u017Eod\u012F -form.please.enter.new=Pra\u0161ome \u0161iam naudotojui \u012Fvesti nauj\u0105 slapta\u017Eod\u012F +form.please.enter.new=Pra\u0161ome \u0161iam naudotojui \u012Fvesti nauj\u0105 slapta\u017Eod\u012F.{0} form.username=Naudotojo vardas found.property=Savyb\u0117 pasirinkta {0} mailto.userlist=Naudotoj\u0173 s\u0105ra\u0161as @@ -38,7 +38,7 @@ new.form.language=Kalba new.form.password.new1=Slapta\u017Eodis new.form.password.new2=Pakartoti slapta\u017Eod\u012F new.form.please.enter=Pra\u0161ome \u012Fvesti naujo naudotojo duomenis -new.form.please.enter.pwd=\u012Eveskite naujo naudotojo slapta\u017Eod\u012F +new.form.please.enter.pwd=\u012Eveskite naujo naudotojo slapta\u017Eod\u012F.{0} new.form.username=Naudotojo vardas new.user.cancel=Veiksmas buvo at\u0161auktas. Naujas naudotojas nesukurtas. new.user.successful=Naujas naudotojas s\u0117kmingai sukurtas diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_nl_NL.properties index 76619cbfe97..57b6c626e52 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_nl_NL.properties @@ -36,7 +36,7 @@ error.search.form.notempty=Gelieve ten minste \u00E9\u00E9n veld in te vullen. error.search.form.to.short=Zoekterm is te kort. form.password.new1=Nieuw wachtwoord form.password.new2=Wachtwoord bevestigen -form.please.enter.new=Gelieve een nieuw wachtwoord voor deze gebruiker in te geven +form.please.enter.new=Gelieve een nieuw wachtwoord voor deze gebruiker in te geven.{0} form.token.new.description=Doormiddel van de knop "Verstuur wachtwoord link" kunt u een wachtwoord link aanmaken en het via e-mail versturen naar uw gebruiker. Door er op te klikken wordt het oud wachtwoord reset waardoor uw gebruiker een nieuw wachtwoord kan instellen. form.token.new.text=Bericht form.token.new.title=Verstuur wachtwoord link @@ -59,7 +59,7 @@ new.form.mandatory=Dit veld is verplicht. new.form.password.new1=Wachtwoord new.form.password.new2=Wachtwoord verifi\u00EBren new.form.please.enter=Gelieve informatie over nieuwe gebruiker in te geven -new.form.please.enter.pwd=Kies een wachtwoord voor een nieuwe gebruiker +new.form.please.enter.pwd=Kies een wachtwoord voor een nieuwe gebruiker.{0} new.form.username=Gebruikersnaam new.user.cancel=Actie geannuleerd. Geen nieuw gebruikersaccount aangemaakt. new.user.successful=Het nieuwe gebruikersaccount werd met succes aangemaakt. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pl.properties index 15548520a35..f4cba13271f 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pl.properties @@ -37,7 +37,7 @@ error.search.form.to.short=Podana fraza jest zbyt kr\u00F3tka error.search.maxResults=Znaleziono zbyt du\u017Cy wynik\u00F3w. Tylko pierwsze {0} z nich zostan\u0105 wy\u015Bwietlone. form.password.new1=Nowe has\u0142o form.password.new2=Potwierd\u017A nowe has\u0142o -form.please.enter.new=Wprowad\u017A nowe has\u0142o dla tego u\u017Cytkownika +form.please.enter.new=Wprowad\u017A nowe has\u0142o dla tego u\u017Cytkownika.{0} form.token.new.description=U\u017Cywaj\u0105c przycisku "Wy\u015Blij link resetowania has\u0142a", utworzysz link, kt\u00F3ry zostanie wys\u0142any mailem do u\u017Cytkownika. Za jego pomoc\u0105, mo\u017Cliwe b\u0119dzie zresetowanie starego has\u0142a i utworzenie nowego. form.token.new.text=Wiadomo\u015B\u0107 form.token.new.title=Wy\u015Blij link resetowania has\u0142a @@ -60,7 +60,7 @@ new.form.mandatory=Pole obowi\u0105zkowe, wpisz warto\u015B\u0107\! new.form.password.new1=Has\u0142o new.form.password.new2=Potwierd\u017A has\u0142o new.form.please.enter=Prosz\u0119 poda\u0107 informacje o nowym u\u017Cytkowniku. -new.form.please.enter.pwd=Wybierz has\u0142o dla nowego u\u017Cytkownika +new.form.please.enter.pwd=Wybierz has\u0142o dla nowego u\u017Cytkownika.{0} new.form.username=Nazwa u\u017Cytkownika new.user.cancel=Akcj\u0119 anulowano. Brak nowych kont u\u017Cytkownika. new.user.successful=Nowe konto u\u017Cytkownika zosta\u0142o utworzone. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_BR.properties index 9023c8fa294..438eb2a0101 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_BR.properties @@ -1,11 +1,8 @@ #Thu May 23 15:11:49 CEST 2019 action.bulkedit=Editar os atributos desses usu\u00E1rios -action.choose=Choose action.choose.finish=Fechar e terminar action.select=Selecionar admins=Administrador -authedit.delete.confirm=Are you sure you want to delete the authentication provider {0} for user {1}? -authedit.delete.success=Authentication provider {0} deleted for user {1}. authors=Autor autocomplete.noresults=$org.olat.core.gui.control.generic.ajax.autocompletion\:autocomplete.noresults autocompletion.info=Pesquisa por login, primeiro nome, \u00FAltimo nome, e-mail ou matr\u00EDcula (n\u00FAmero de registro) @@ -15,11 +12,9 @@ bulkChange.failed=Nenhuma modifica\u00E7\u00E3o feita bulkChange.partialsuccess={0} de {1} modifica\u00E7\u00F5es sucedidas. Os seguintes atributos de usu\u00E1rio n\u00E3o poderam ser modificados\: {3} bulkChange.success=Modifica\u00E7\u00E3o completada com sucesso bulkChange.title=Modifica\u00E7\u00E3o de atributos de usu\u00E1rio -changeuserpwd.cancel=Action was cancelled. Password remains unchanged. changeuserpwd.failed=Sua nova senha n\u00E3o pode ser salva. Houve um erro inesperado no servidor. changeuserpwd.successful=New password saved successfully. It is valid from now on. clear=Limpar -command.mail=Send e-mail to these users confirm.clear.identity=Deseja realmente limpar o nome e sobrenome desse usu\u00E1rio exclu\u00EDdo "{0}"? content.usermgmt.text1=Aqui voc\u00EA pode modificar ou gerenciar dados de usu\u00E1rios existentes do OLAT. Favor iniciar sua busca de usu\u00E1rio. content.usermgmt.title=Gerenciamento do usu\u00E1rio @@ -28,20 +23,10 @@ delete.pending.registration.confirmation=Existe um auto-registro pendente para o delete.pending.registration.confirmation.title=Excluir auto registro deleted.user.list=Lista de usu\u00E1rios exclu\u00EDdos deselectall=$org.olat.core.gui.components.table\:uncheckall -edit.uauth=Authentications edit.uhomepage=Cart\u00E3o de visitas -edit.uprefs=System settings -edit.uprofile=User profile -edit.uprop=Properties -edit.upwd=Change password -edit.uquota=Quota edit.urelations=Rela\u00E7\u00F5es -edit.uroles=Roles email.notsent=$org.olat.user\:email.notsent email.sent=$org.olat.user\:email.sent -error.no.user.found=No user was found with these attributes. Please try again. -error.noaccess.to.user=You do not have enough rights to edit this user. Please contact {0}. -error.password.nomatch=The two new passwords do not match. error.roles.atleastone=Pelo menos um papel \u00E9 obrigat\u00F3rio error.roles.atleastone.userorinvitee=Pelo menos uma fun\u00E7\u00E3o "$\:role.user" ou "$\:role.invitee" \u00E9 obrigat\u00F3ria. error.search.form.no.valid.datechooser=Por favor, indique uma data v\u00E1lida. @@ -51,13 +36,9 @@ error.search.form.to.short=Termo de pesquisa muito curto. error.search.maxResults=Muitos resultados encontrados. Apenas o primeiro {0} s\u00E3o exibidos. export.user.data=Exportar dados export.user.data.title=Exportar dados do usu\u00E1rio "{0}" -form.password.new1=New password -form.password.new2=Confirm password -form.please.enter.new=Please enter a new password for this user form.token.new.description=Atrav\u00E9s do bot\u00E3o "Enviar link da senha" voc\u00EA pode criar um link de senha e envi\u00E1-lo via e-mail para o usu\u00E1rio. Ao clicar sobre ele a senha antiga ser\u00E1 exclu\u00EDda permitindo que seu usu\u00E1rio defina uma nova. form.token.new.text=Mensagem form.token.new.title=Enviar link de senha -form.username=User name found.property=Property selected groupmanagers=Gestor de grupo header.autocompletion=Busca combinada com auto-completar @@ -65,22 +46,15 @@ header.normal=Pesquisa com atributos de usu\u00E1rio instoresmanager=Gestor de recurso did\u00E1tico mailtemplate.login.denied.body=Sua conta OpenOLAT {0} com o endere\u00E7o de e-mail {1} est\u00E1 bloqueada.\r\n\r\n\r\nSe voc\u00EA n\u00E3o concorda com esta mudan\u00E7a, por favor, contate o suporte imediatamente em {3}. mailtemplate.login.denied.subject=Conta OpenOLAT bloqueada -mailto.userlist=List of users msg.selectionempty=Favor selecione pelo menos um usu\u00E1rio. -new.error.email.choosen=This e-mail address already exists. There is no need to create another account for this user. No data saved. -new.error.loginname.choosen=This user name has already been allocated. Please try another one. new.error.loginname.empty=$org.olat.user\:form.checkUsername -new.error.password.nomatch=The two passwords do not match. new.error.property.invalid=Entrada invalida\! new.form.auth=OLAT password -new.form.auth.false=Do not create now -new.form.auth.true=Create now -new.form.language=Language new.form.mandatory=Campo obrigat\u00EDrio, entrar com um valor\! new.form.organisations=Organiza\u00E7\u00E3o new.form.password.new1=Password new.form.password.new2=Verify password -new.form.please.enter=Please enter information on new user +new.form.please.enter=Please enter information on new user new.form.please.enter.pwd=Choose a password for new user new.form.username=User name new.user.cancel=Action cancelled. No new user account created. @@ -92,14 +66,10 @@ notification.noSubscription=Voc\u00EA n\u00E3o est\u00E1 inscrito para receber n owner=Propriet\u00E1rio do Curso poolsmanager=Gestor do banco de perguntas repocoach=Coach de Curso -rightForm.error.anonymous.no.roles=Anonymous guests can not exercise system roles rightsForm.add.to.organisation=Adicionar \u00E0 organiza\u00E7\u00E3o -rightsForm.guest=User type -rightsForm.isLoginDenied=Login blocked rightsForm.roles=Fun\u00E7\u00F5es rightsForm.roles.for=Fun\u00E7\u00F5es para "{0}" rightsForm.sendLoginDeniedEmail=Notificar o usu\u00E1rio sobre acesso negado -rightsForm.status=Status rightsForm.status.activ=Ativo rightsForm.status.any.visible=- rightsForm.status.deleted=Deletado @@ -107,14 +77,7 @@ rightsForm.status.login_denied=Login bloqueado rightsForm.status.pending=Pendente rightsForm.status.permanent=N\u00E3o delet\u00E1vel rightsForm.title=Assign system roles and rights -role.Admin=System administrator -role.administrator=administrator -role.author=Author role.curriculummanager=Gerente de curr\u00EDculo -role.groupmanager=Group management -role.guest=Anonymous guest -role.guest.false=System user -role.guest.true=Anonymous guest role.invitee=Convidado role.learnresourcemanager=Gestor de recurso did\u00E1tico role.lecturemanager=Gerente de Palestras @@ -125,10 +88,6 @@ role.qualitymanager=Gerente de qualidade role.rolesmanager=Gestor de fun\u00E7\u00F5es role.sysadmin=Administrador do sistema role.user=Usu\u00E1rio -role.usermanager=User management -search.cancel=Action cancelled. -search.form.afterDate=User created after -search.form.beforeDate=User created before search.form.constraint.administrator=$\:role.administrator search.form.constraint.auth.LDAP=Senha LDAP search.form.constraint.auth.OAuth=Autentica\u00E7\u00E3o de rede social / Single Sign-On (OAuth) @@ -137,10 +96,7 @@ search.form.constraint.auth.PerformX=PerformX search.form.constraint.auth.Shib=Shibboleth password search.form.constraint.auth.ShibGeneric=$\:search.form.constraint.auth.Shib search.form.constraint.auth.WEBDAV=Senha WebDAV -search.form.constraint.auth.none=No authentication -search.form.constraint.author=Author search.form.constraint.curriculummanager=$\:role.curriculummanager -search.form.constraint.groupmanager=Group manager search.form.constraint.guest=$\:role.guest search.form.constraint.invitee=$\:role.invitee search.form.constraint.learnresourcemanager=Gestor de recurso did\u00E1tico @@ -153,7 +109,6 @@ search.form.constraint.qualitymanager=$\:role.qualitymanager search.form.constraint.rolesmanager=$\:role.rolesmanager search.form.constraint.sysadmin=$\:role.sysadmin search.form.constraint.user=$\:role.user -search.form.constraint.usermanager=User manager search.form.id=ID search.form.login=Nome do usu\u00E1rio search.form.title.authentications=Authentication restrictions @@ -167,13 +122,6 @@ search.form.userLoginBeforeDate=\u00DAltimo usu\u00E1rio logado antes select.organisation=Organiza\u00E7\u00E3o selectall=$org.olat.core.gui.components.table\:checkall sendtoken.wrong.auth=Este usu\u00E1rio possui tokens de autentica\u00E7\u00E3o que n\u00E3o podem ser alterados usando este link de senha. Examine e exclua esses tokens de autentica\u00E7\u00E3o adicionais primeiro. -submit.cancel=Cancel -submit.save=Save -submit.search=Search -table.auth.credential=Authorization -table.auth.login=User name -table.auth.provider=Provider -table.header.action=Action table.header.vcard=Cart\u00E3o de visitas table.identity.action=A\u00E7\u00E3o table.identity.creationdate=Criado @@ -188,21 +136,8 @@ table.identity.status=Status table.identity.vcard=<i class\='o_icon o_icon-lg o_icon_home'> </i> table.name.firstName=Nome table.name.lastName=\u00DAltimo nome -table.user.login=User name table.user.select=$org.olat.core.gui.components.table\:table.header.multiselect title.exeUAuths=Authentications -title.exeUPrefs=System settings of {0} -title.exeUProfile=User profile of {0} -title.exeUProps=Properties of {0} -title.exeUPwd=Change password for user {0} -title.exeUQuota=Quota in personal folder -title.mail=Send e-mail to list of users -title.newuser=Create new user -title.user.new=Create new OLAT user account -title.user.search=Search for an OLAT user -title.userlist=User list -title.usersearch=User search -user.found=User was found usermanagers=Gestor de usu\u00E1rios view.access=Reservas view.competences=Compet\u00EAncias diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_PT.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_PT.properties index 3c8e6c41768..c5f751560ad 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_PT.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_pt_PT.properties @@ -1,107 +1,31 @@ #Fri Mar 23 15:02:47 CET 2018 -action.choose=Choose action.select=Selecionar -authedit.delete.confirm=Are you sure you want to delete the authentication provider {0} for user {1}? -authedit.delete.success=Authentication provider {0} deleted for user {1}. autocomplete.noresults=$org.olat.core.gui.control.generic.ajax.autocompletion\:autocomplete.noresults autocompletion.info=Pesquisa por login, primeiro nome, \u00FAltimo nome, e-mail ou matr\u00EDcula (n\u00FAmero de registro) -changeuserpwd.cancel=Action was cancelled. Password remains unchanged. -changeuserpwd.successful=New password saved successfully. It is valid from now on. -command.mail=Send e-mail to these users content.usermgmt.text1=Aqui voc\u00EA pode modificar ou gerenciar dados de usu\u00E1rios existentes do OLAT. Favor iniciar sua busca de usu\u00E1rio. content.usermgmt.title=Gerenciamento do usu\u00E1rio content.usermgmt.userfound=Gerenciar configura\u00E7\u00F5es de usu\u00E1rio edit.uauth=Authentications -edit.uprefs=System settings -edit.uprofile=User profile -edit.uprop=Properties -edit.upwd=Change password -edit.uquota=Quota -edit.uroles=Roles -error.no.user.found=No user was found with these attributes. Please try again. -error.noaccess.to.user=You do not have enough rights to edit this user. Please contact {0}. -error.password.nomatch=The two new passwords do not match. -error.search.form.notempty=Please fill in at least one of the available fields. -form.password.new1=New password -form.password.new2=Confirm password -form.please.enter.new=Please enter a new password for this user -form.username=User name -found.property=Property selected header.autocompletion=Busca combinada com auto-completar header.normal=Pesquisa com atributos de usu\u00E1rio -mailto.userlist=List of users -new.error.email.choosen=This e-mail address already exists. There is no need to create another account for this user. No data saved. -new.error.loginname.choosen=This user name has already been allocated. Please try another one. new.error.loginname.empty=$org.olat.user\:form.checkUsername -new.error.password.nomatch=The two passwords do not match. -new.form.auth=OLAT password -new.form.auth.false=Do not create now -new.form.auth.true=Create now -new.form.language=Language -new.form.password.new1=Password -new.form.password.new2=Verify password -new.form.please.enter=Please enter information on new user -new.form.please.enter.pwd=Choose a password for new user -new.form.username=User name -new.user.cancel=Action cancelled. No new user account created. -new.user.successful=The new user account has been created successfully. -rightForm.error.anonymous.no.roles=Anonymous guests can not exercise system roles -role.administrator=Administrator -role.guest=Anonymous guest -role.guest.false=System user -role.guest.true=Anonymous guest -role.author=Author -role.groupmanager=Group management -rightsForm.isLoginDenied=Login blocked -role.usermanager=User management -role.sysadmin=System administrator -rightsForm.guest=User type -rightsForm.status=Status rightsForm.status.activ=Ativo rightsForm.status.any.visible=- rightsForm.status.deleted=Deletado rightsForm.status.login_denied=Login bloqueado rightsForm.status.permanent=N\u00E3o delet\u00E1vel rightsForm.title=Assign system roles and rights -search.cancel=Action cancelled. -search.form.afterDate=User created after -search.form.beforeDate=User created before search.form.constraint.administrator=$\:role.administrator search.form.constraint.auth.OLAT=OLAT/WebDAV password search.form.constraint.auth.Shib=Shibboleth password -search.form.constraint.auth.none=No authentication -search.form.constraint.author=Author -search.form.constraint.groupmanager=Group manager -search.form.constraint.logindenied=Account blocked -search.form.constraint.usermanager=User manager search.form.login=Nome do usu\u00E1rio search.form.title.authentications=Authentication restrictions search.form.title.date=Creation date restrictions search.form.title.roles=System role restrictions search.form.title.user=Restri\u00E7\u00F5es de usu\u00E1rio -submit.cancel=Cancel -submit.save=Save -submit.search=Search table.auth.credential=Authorization -table.auth.login=User name -table.auth.provider=Provider -table.header.action=Action table.identity.action=A\u00E7\u00E3o table.identity.creationdate=Criado table.identity.lastlogin=Ultimo Login table.identity.name=Nome de usu\u00E1rio table.identity.vcard=<i class\='o_icon o_icon-lg o_icon_home'> </i> -table.user.login=User name -title.exeUAuths=Authentications -title.exeUPrefs=System settings of {0} -title.exeUProfile=User profile of {0} -title.exeUProps=Properties of {0} -title.exeUPwd=Change password for user {0} -title.exeUQuota=Quota in personal folder -title.mail=Send e-mail to list of users -title.newuser=Create new user -title.user.new=Create new OLAT user account -title.user.search=Search for an OLAT user -title.userlist=User list -title.usersearch=User search -user.found=User was found diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ru.properties index c9b82dae73b..2b236264c04 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ru.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_ru.properties @@ -24,7 +24,7 @@ error.password.nomatch=\u041E\u0431\u0430 \u043D\u043E\u0432\u044B\u0445 \u043F\ error.search.form.notempty=\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u0435 \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C \u043E\u0434\u043D\u043E \u043F\u043E\u043B\u0435, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430. form.password.new1=\u041D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C form.password.new2=\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C -form.please.enter.new=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u044F \u0434\u0430\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430. +form.please.enter.new=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u044F \u0434\u0430\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430.{0} form.username=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F found.property=\u0421\u0432\u043E\u0439\u0441\u0442\u0432\u043E \u0432\u044B\u0431\u0440\u0430\u043D\u043E header.autocompletion=\u041F\u043E\u0438\u0441\u043A \u0441 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u043C \u0434\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435\u043C @@ -41,7 +41,7 @@ new.form.language=\u042F\u0437\u044B\u043A new.form.password.new1=\u041F\u0430\u0440\u043E\u043B\u044C new.form.password.new2=\u0412\u0435\u0440\u0438\u0444\u0438\u0446\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C new.form.please.enter=\u0414\u0430\u043D\u043D\u044B\u0435 \u043E \u043B\u0438\u0447\u043D\u043E\u0441\u0442\u0438 \u043D\u043E\u0432\u043E\u0439 \u0443\u0447\u0451\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F -new.form.please.enter.pwd=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F +new.form.please.enter.pwd=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u044C \u0434\u043B\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F.{0} new.form.username=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F new.user.cancel=\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u0430. \u041D\u043E\u0432\u0430\u044F \u0443\u0447\u0451\u0442\u043D\u0430\u044F \u0437\u0430\u043F\u0438\u0441\u044C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u0430. new.user.successful=\u0421\u043E\u0437\u0434\u0430\u043D\u0430 \u043D\u043E\u0432\u0430\u044F \u0443\u0447\u0451\u0442\u043D\u0430\u044F \u0437\u0430\u043F\u0438\u0441\u044C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_sq.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_sq.properties index d318b796efd..86cb19d7468 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_sq.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_sq.properties @@ -24,7 +24,7 @@ error.password.nomatch=Dy fjal\u00EBkalimet e reja nuk p\u00EBrputhen. error.search.form.notempty=Ju lutemi mbushni t\u00EB pakt\u00EBn nj\u00EB nga fushat e gatshme. form.password.new1=Fjal\u00EBkalimi i ri form.password.new2=Mirato fjal\u00EBkalimin -form.please.enter.new=Ju lutemi shkruani fjal\u00EBkalimin e ri p\u00EBr k\u00EBt\u00EB shfryt\u00EBzues +form.please.enter.new=Ju lutemi shkruani fjal\u00EBkalimin e ri p\u00EBr k\u00EBt\u00EB shfryt\u00EBzues.{0} form.username=Emri i shfryt\u00EBzuesit found.property=Tipar i p\u00EBrzgjedhur {0} header.autocompletion=K\u00EBrko me Autokompletim @@ -43,7 +43,7 @@ new.form.mandatory=Kjo \u00EBsht\u00EB nj\u00EB fush\u00EB e detyrueshme, ju lut new.form.password.new1=Fjal\u00EBkalimi new.form.password.new2=V\u00EBrteto fjal\u00EBkalimin new.form.please.enter=Ju lutemi shkruani informata p\u00EBr shfryt\u00EBzuesin e ri -new.form.please.enter.pwd=P\u00EBrzgjedh nj\u00EB fjal\u00EBkalim p\u00EBr shfryt\u00EBzuesin e ri +new.form.please.enter.pwd=P\u00EBrzgjedh nj\u00EB fjal\u00EBkalim p\u00EBr shfryt\u00EBzuesin e ri.{0} new.form.username=Emri i shfryt\u00EBzuesit new.user.cancel=Aksioni u anulua. Nuk u krijua ndonj\u00EB llogari. new.user.successful=Llogaria e shfryt\u00EBzuesit t\u00EB ri u krijuar me sukses. diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_CN.properties index 9024f4ebd2f..f7619bb3e12 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_CN.properties @@ -36,7 +36,6 @@ error.search.form.notempty=\u8BF7\u81F3\u5C11\u586B\u5199\u4E00\u9879 error.search.form.to.short=\u641C\u7D22\u5185\u5BB9\u8FC7\u77ED\uFF01 form.password.new1=\u65B0\u5BC6\u7801 form.password.new2=\u65B0\u5BC6\u7801\u786E\u8BA4 -form.please.enter.new=\u8BF7\u7ED9\u8BE5\u7528\u6237\u8BBE\u7F6E\u4E00\u4E2A\u65B0\u5BC6\u7801 form.token.new.description=\u901A\u8FC7\u6309\u94AE"\u53D1\u9001\u5BC6\u7801\u94FE\u63A5"\u60A8\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A\u5BC6\u7801\u94FE\u63A5\uFF0C\u5E76\u4F7F\u7528E-mail\u5C06\u6B64\u94FE\u63A5\u53D1\u9001\u7ED9\u7528\u6237\u3002\u5F53\u70B9\u51FB\u6B64\u94FE\u63A5\u65F6\uFF0C\u65E7\u5BC6\u7801\u4F1A\u66F4\u65B0\uFF0C\u540C\u65F6\u5141\u8BB8\u7528\u6237\u8F93\u5165\u65B0\u5BC6\u7801\u3002 form.token.new.text=\u6D88\u606F form.token.new.title=\u53D1\u9001\u5BC6\u7801\u94FE\u63A5 @@ -59,7 +58,6 @@ new.form.mandatory=\u8FD9\u662F\u4EBA\u5DE5\u64CD\u4F5C\u90E8\u5206\uFF0C\u8BF7\ new.form.password.new1=\u5BC6\u7801 new.form.password.new2=\u68C0\u9A8C\u5BC6\u7801 new.form.please.enter=\u8BF7\u8F93\u5165\u65B0\u7528\u6237\u4FE1\u606F -new.form.please.enter.pwd=\u4E3A\u65B0\u7528\u6237\u9009\u62E9\u5BC6\u7801 new.form.username=\u7528\u6237\u540D new.user.cancel=\u64CD\u4F5C\u53D6\u6D88\u3002\u672A\u521B\u5EFA\u7528\u6237\u3002 new.user.successful=\u6210\u529F\u521B\u5EFA\u65B0\u7528\u6237 diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_TW.properties index fdf41fc3e1e..46e03b14bc3 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_zh_TW.properties @@ -33,7 +33,6 @@ error.password.nomatch=\u9019\u5169\u500B\u65B0\u7684\u5BC6\u78BC\u4E0D\u4E00\u8 error.search.form.notempty=\u8ACB\u81F3\u5C11\u586B\u5BEB\u4E00\u500B\u6B04\u4F4D\u3002 form.password.new1=\u65B0\u7684\u5BC6\u78BC form.password.new2=\u78BA\u8A8D\u5BC6\u78BC -form.please.enter.new=\u8ACB\u70BA\u9019\u500B\u4F7F\u7528\u8005\u8F38\u5165\u4E00\u500B\u65B0\u7684\u5BC6\u78BC form.token.new.description=\u85C9\u7531\u6309\u9215\u300C\u767C\u9001\u5BC6\u78BC\u9023\u7D50\u300D\u60A8\u53EF\u4EE5\u5EFA\u7ACB\u4E00\u500B\u5BC6\u78BC\u9023\u7D50\u4E26\u900F\u904E\u96FB\u5B50\u90F5\u4EF6\u50B3\u9001\u5B83\u7D66\u60A8\u7684\u4F7F\u7528\u8005\u3002\u7576\u9EDE\u64CA\u5B83\u6642\uFF0C\u820A\u7684\u5BC6\u78BC\u5C07\u88AB\u91CD\u8A2D\uFF0C\u5141\u8A31\u60A8\u7684\u4F7F\u7528\u8005\u8A2D\u5B9A\u4E00\u500B\u65B0\u7684\u5BC6\u78BC\u3002 form.token.new.text=\u8A0A\u606F form.token.new.title=\u767C\u9001\u5BC6\u78BC\u9023\u7D50 @@ -56,7 +55,6 @@ new.form.mandatory=\u9019\u662F\u4E00\u500B\u5FC5\u586B\u6B04\u4F4D\uFF0C\u8ACB\ new.form.password.new1=\u5BC6\u78BC new.form.password.new2=\u78BA\u8A8D\u5BC6\u78BC new.form.please.enter=\u8ACB\u8F38\u5165\u65B0\u4F7F\u7528\u8005\u7684\u8CC7\u8A0A -new.form.please.enter.pwd=\u9078\u64C7\u4E00\u500B\u5BC6\u78BC\u7D66\u65B0\u4F7F\u7528\u8005 new.form.username=\u4F7F\u7528\u8005\u540D\u7A31 new.user.cancel=\u52D5\u4F5C\u53D6\u6D88\u3002\u6C92\u6709\u65B0\u7684\u4F7F\u7528\u8005\u5E33\u865F\u88AB\u5EFA\u7ACB\u3002 new.user.successful=\u65B0\u7684\u4F7F\u7528\u8005\u5E33\u865F\u5DF2\u88AB\u6210\u529F\u5730\u5EFA\u7ACB\u4E86\u3002 diff --git a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java index 4cef2ade28a..3a8ffb6224f 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java +++ b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeManager.java @@ -19,6 +19,8 @@ */ package org.olat.admin.user.bulkChange; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import java.io.StringWriter; import java.util.ArrayList; import java.util.List; @@ -26,6 +28,7 @@ import java.util.Locale; import java.util.Map; import java.util.Properties; +import org.apache.logging.log4j.Logger; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; @@ -42,7 +45,6 @@ import org.olat.core.id.Preferences; import org.olat.core.id.Roles; import org.olat.core.id.User; import org.olat.core.id.UserConstants; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; @@ -54,6 +56,8 @@ import org.olat.core.util.mail.MailPackage; import org.olat.group.BusinessGroupService; import org.olat.group.model.BusinessGroupMembershipChange; import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.GenderPropertyHandler; import org.olat.user.propertyhandlers.UserPropertyHandler; @@ -106,13 +110,13 @@ public class UserBulkChangeManager implements InitializingBean { } } - public void changeSelectedIdentities(List<Identity> selIdentities, UserBulkChanges userBulkChanges, List<String> notUpdatedIdentities, boolean isAdministrativeUser, Translator trans, Identity actingIdentity, Roles actingRoles) { Translator transWithFallback = userManager.getPropertyHandlerTranslator(trans); String usageIdentifyer = UserBulkChangeStep00.class.getCanonicalName(); + SyntaxValidator syntaxValidator = olatAuthManager.createPasswordSytaxValidator(); notUpdatedIdentities.clear(); List<Identity> changedIdentities = new ArrayList<>(); @@ -142,18 +146,21 @@ public class UserBulkChangeManager implements InitializingBean { // change pwd if (attributeChangeMap.containsKey(CRED_IDENTIFYER)) { - String newPwd = attributeChangeMap.get(CRED_IDENTIFYER); - if (StringHelper.containsNonWhitespace(newPwd)) { - if (!userManager.syntaxCheckOlatPassword(newPwd)) { - errorDesc = transWithFallback.translate("error.password"); + String password = attributeChangeMap.get(CRED_IDENTIFYER); + if (StringHelper.containsNonWhitespace(password)) { + ValidationResult validationResult = syntaxValidator.validate(password, identity); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), + transWithFallback.getLocale()); + errorDesc = transWithFallback.translate("error.password", new String[] { descriptions }); updateError = true; } } else { - newPwd = null; + password = null; } if (canManagedCritical) { - olatAuthManager.changePasswordAsAdmin(identity, newPwd); + olatAuthManager.changePasswordAsAdmin(identity, password); } else { errorDesc = transWithFallback.translate("error.password"); } diff --git a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep00.java b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep00.java index 8b1cb770abf..4d66ab6a6a6 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep00.java +++ b/src/main/java/org/olat/admin/user/bulkChange/UserBulkChangeStep00.java @@ -19,6 +19,8 @@ */ package org.olat.admin.user.bulkChange; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -49,6 +51,9 @@ import org.olat.core.gui.control.generic.wizard.StepsRunContext; import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; import org.olat.core.util.i18n.I18nManager; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.user.ProfileFormController; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.GenericUnique127CharTextPropertyHandler; @@ -96,6 +101,7 @@ class UserBulkChangeStep00 extends BasicStep { private final List<MultipleSelectionElement> checkBoxes = new ArrayList<>(); private final boolean isAdministrativeUser; + private final SyntaxValidator syntaxValidator; @Autowired private I18nManager i18nManager; @@ -105,6 +111,8 @@ class UserBulkChangeStep00 extends BasicStep { private UserBulkChangeManager ubcMan; @Autowired private BaseSecurityModule securityModule; + @Autowired + private OLATAuthManager olatAuthManager; public UserBulkChangeStepForm00(UserRequest ureq, WindowControl control, Form rootForm, StepsRunContext runContext) { super(ureq, control, rootForm, runContext, LAYOUT_VERTICAL, null); @@ -112,6 +120,7 @@ class UserBulkChangeStep00 extends BasicStep { setTranslator(userManager.getPropertyHandlerTranslator(getTranslator())); flc.setTranslator(getTranslator()); isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles()); + this.syntaxValidator = olatAuthManager.createPasswordSytaxValidator(); initForm(ureq); } @@ -187,8 +196,8 @@ class UserBulkChangeStep00 extends BasicStep { if (handler.getName().equals(formItem.getName())) { // first check on mandatoryness if (userManager.isMandatoryUserProperty(usageIdentifyer, handler) && !StringHelper.containsNonWhitespace(evaluatedInputFieldValue)) { - formItem.setErrorKey("form.name." + handler.getName() + ".error.empty", null); - return false; + formItem.setErrorKey("form.name." + handler.getName() + ".error.empty", null); + return false; } // second check on property content ValidationError valicationError = new ValidationError(); @@ -202,9 +211,15 @@ class UserBulkChangeStep00 extends BasicStep { } // special case: check password-syntax: - if (propertyField.getName().equals("password")&& !userManager.syntaxCheckOlatPassword(evaluatedInputFieldValue)) { - propertyField.setErrorKey("error.password", new String[] { evaluatedInputFieldValue }); - return false; + if (propertyField.getName().equals("password")) { + String password = propertyField.getValue(); + // No identity :-( + ValidationResult validationResult = syntaxValidator.validate(password); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + propertyField.setErrorKey("error.password", new String[] { descriptions }); + return false; + } } } } diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_ar.properties index 66395c4201f..41ec8b062e1 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_ar.properties @@ -3,7 +3,7 @@ bulk.auto.disc=\u0642\u0628\u0648\u0644 \u0634\u0631\u0648\u0637 \u0627\u0644\u0 bulk.psw.newpsw=\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 bulk.psw.submit=\u062A\u0646\u0641\u064A\u0630 bulk.psw.users=\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=\u0627\u0644\u0644\u063A\u0629 form.name.pwd=\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 main.menu.title=\u0643\u0644\u0645\u0629 \u0645\u0631\u0648\u0631 \u0623\u0648\u0644\u0627\u062A diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_bg.properties index 16af69d14b1..6ec4d8fe07c 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_bg.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_bg.properties @@ -1,5 +1,5 @@ #Thu Jul 16 16:08:41 CEST 2009 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=\u0415\u0437\u0438\u043A form.name.pwd=\u041F\u0430\u0440\u043E\u043B\u0430 role.add=\u041F\u0440\u0438\u0431\u0430\u0432\u0435\u0442\u0435 diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_cs.properties index f8bb5fba7b2..dca50c4c203 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_cs.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_cs.properties @@ -1,5 +1,5 @@ #Mon Mar 02 09:54:13 CET 2009 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Jazyk form.name.pwd=Heslo role.add=Vlo\u017Eit diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties index 5e5ebcac4c9..44325d35344 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_de.properties @@ -1,5 +1,5 @@ #Mon Mar 02 09:54:04 CET 2009 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Sprache form.name.pwd=Passwort role.add=hinzuf\u00FCgen @@ -35,12 +35,12 @@ table.role.removed=Entfernte Rolle table.user.login=Benutzername title=\u00C4nderung von Benutzer-Attributen main.menu.title=OLAT Passwort -main.menu.title.alt=Massen\u00e4nderung des OLAT Passworts +main.menu.title.alt=Massen\u00E4nderung des OLAT Passworts bulk.psw.users=Benutzerliste bulk.psw.newpsw=Passwort -bulk.psw.submit=Ausf\u00fchren +bulk.psw.submit=Ausf\u00FChren bulk.psw.done={0} Benutzer bearbeitet. bulk.auto.disc=Nutzungsbedingungen akzeptieren bulk.lang.german=Systemsprache auf Deutsch setzen -step1a.description=Gruppe(n) ausw\u00e4hlen -add.to.groups=Die Benutzer werden ausserdem folgenden Gruppen hinzugef\u00fcgt. +step1a.description=Gruppe(n) ausw\u00E4hlen +add.to.groups=Die Benutzer werden ausserdem folgenden Gruppen hinzugef\u00FCgt. diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_el.properties index 1a26678a47f..1602aff0a2e 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_el.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_el.properties @@ -5,7 +5,7 @@ bulk.psw.done=\u03A4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03B9\u03AE\u03B8\u03B7 bulk.psw.newpsw=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 bulk.psw.submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE bulk.psw.users=\u039B\u03AF\u03C3\u03C4\u03B1 \u03C7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=\u0393\u03BB\u03CE\u03C3\u03C3\u03B1 form.name.pwd=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 main.menu.title=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 OLAT diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties index dc03082029c..4100e7dd8d3 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_en.properties @@ -5,7 +5,7 @@ bulk.psw.done={0} users edited. bulk.psw.newpsw=Password bulk.psw.submit=Submit bulk.psw.users=User list -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Language form.name.pwd=Password main.menu.title=OLAT password diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_es.properties index af85d417e6e..5c95e36ede5 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_es.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_es.properties @@ -1,5 +1,5 @@ #Mon Mar 09 05:14:49 CET 2009 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Idioma form.name.pwd=Contrase\u00F1a role.add=Agregar diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_fr.properties index 1a3238acc19..d6ccdb9ea72 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_fr.properties @@ -6,7 +6,7 @@ bulk.psw.done={0} utilisateurs trait\u00E9s. bulk.psw.newpsw=Mot de passe bulk.psw.submit=Ex\u00E9cuter bulk.psw.users=Liste utilisateurs -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=langue form.name.pwd=mot de passe main.menu.title=Mot de passe OLAT diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_it.properties index 27eee4bd11c..b00c9ec7f4d 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_it.properties @@ -6,7 +6,7 @@ bulk.psw.done={0} utenti elaborati. bulk.psw.newpsw=Password bulk.psw.submit=Eseguire bulk.psw.users=Lista utenti -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Lingua form.name.pwd=Password main.menu.title=Password OLAT diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_jp.properties index ec665a4deeb..0df0c3442f1 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_jp.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_jp.properties @@ -5,7 +5,7 @@ bulk.psw.done={0} \u30E6\u30FC\u30B6\u304C\u7DE8\u96C6\u3055\u308C\u307E\u3057\u bulk.psw.newpsw=\u30D1\u30B9\u30EF\u30FC\u30C9 bulk.psw.submit=\u9001\u4FE1 bulk.psw.users=\u30E6\u30FC\u30B6\u30EA\u30B9\u30C8 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=\u8A00\u8A9E form.name.pwd=\u30D1\u30B9\u30EF\u30FC\u30C9 main.menu.title=OLAT\u30D1\u30B9\u30EF\u30FC\u30C9 diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_nl_NL.properties index 9d8ce953c41..a57668277ec 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_nl_NL.properties @@ -5,7 +5,7 @@ bulk.psw.done={0} gebruikers aangepast. bulk.psw.newpsw=Wachtwoord bulk.psw.submit=Ingeven bulk.psw.users=Gebruikerslijst -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Taal form.name.pwd=Wachtwoord main.menu.title=OLAT wachtwoord diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pl.properties index c7fa9aed3e7..a5071983ce6 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pl.properties @@ -6,7 +6,7 @@ bulk.psw.done={0} edytowanych u\u017Cytkownik\u00F3w. bulk.psw.newpsw=Has\u0142o bulk.psw.submit=Zatwierd\u017A bulk.psw.users=Lista u\u017Cytkownik\u00F3w -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=J\u0119zyk form.name.pwd=Has\u0142o main.menu.title=Has\u0142o OLAT diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pt_BR.properties index e348d220ec4..369d45df1a5 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_pt_BR.properties @@ -6,7 +6,7 @@ bulk.psw.done={0} usu\u00E1rios editados bulk.psw.newpsw=Senha bulk.psw.submit=Enviar bulk.psw.users=Lista de usu\u00E1rios -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Idioma form.name.pwd=Senha main.menu.title=Senha OLAT diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_sq.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_sq.properties index c95cd828b56..c647019789c 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_sq.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_sq.properties @@ -1,5 +1,5 @@ #Mon Mar 02 09:54:11 CET 2009 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=Gjuha form.name.pwd=Fjal\u00EBkalimi role.add=shto diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_CN.properties index f773992ac94..8a86736e1b4 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_CN.properties @@ -5,7 +5,7 @@ bulk.psw.done={0}\u7528\u6237\u7F16\u8F91\u8FC7\u3002 bulk.psw.newpsw=\u5BC6\u7801 bulk.psw.submit=\u63D0\u4EA4 bulk.psw.users=\u7528\u6237\u5217\u8868 -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=\u8BED\u8A00 form.name.pwd=\u5BC6\u7801 role.add=\u6DFB\u52A0 diff --git a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_TW.properties index aa56a1ca642..1f47a85f880 100644 --- a/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/admin/user/bulkChange/_i18n/LocalStrings_zh_TW.properties @@ -5,7 +5,7 @@ bulk.psw.done={0} \u500B\u4F7F\u7528\u8005\u88AB\u7DE8\u8F2F\u3002 bulk.psw.newpsw=\u5BC6\u78BC bulk.psw.submit=\u9001\u51FA bulk.psw.users=\u4F7F\u7528\u8005\u6E05\u55AE -error.password=$org.olat.user\:form.checkPassword +error.password=$org.olat.user\:error.password.invalid form.name.language=\u8A9E\u8A00 form.name.pwd=\u5BC6\u78BC main.menu.title=OLAT \u5BC6\u78BC diff --git a/src/main/java/org/olat/admin/user/imp/ImportStep00.java b/src/main/java/org/olat/admin/user/imp/ImportStep00.java index 9804f7f8e4b..70075de371f 100644 --- a/src/main/java/org/olat/admin/user/imp/ImportStep00.java +++ b/src/main/java/org/olat/admin/user/imp/ImportStep00.java @@ -24,10 +24,13 @@ */ package org.olat.admin.user.imp; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -56,6 +59,9 @@ import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.core.util.StringHelper; import org.olat.core.util.i18n.I18nModule; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.shibboleth.ShibbolethDispatcher; import org.olat.shibboleth.ShibbolethModule; import org.olat.user.UserManager; @@ -104,6 +110,9 @@ class ImportStep00 extends BasicStep { private List<UpdateIdentity> updateIdents; private List<TransientIdentity> newIdents; private List<UserPropertyHandler> userPropertyHandlers; + + private final SyntaxValidator passwordSyntaxValidator; + private final SyntaxValidator usernameSyntaxValidator; @Autowired private UserManager um; @@ -112,6 +121,8 @@ class ImportStep00 extends BasicStep { @Autowired private I18nModule i18nModule; @Autowired + private OLATAuthManager olatAuthManager; + @Autowired private BaseSecurity securityManager; @Autowired private ShibbolethModule shibbolethModule; @@ -119,6 +130,8 @@ class ImportStep00 extends BasicStep { public ImportStepForm00(UserRequest ureq, WindowControl control, Form rootForm, StepsRunContext runContext) { super(ureq, control, rootForm, runContext, LAYOUT_VERTICAL, null); flc.setTranslator(getTranslator()); + this.usernameSyntaxValidator = olatAuthManager.createUsernameSytaxValidator(); + this.passwordSyntaxValidator = olatAuthManager.createPasswordSytaxValidator(); initForm(ureq); } @@ -192,11 +205,6 @@ class ImportStep00 extends BasicStep { // login row if (parts.length > columnId) { login = parts[columnId].trim(); - if (!UserManager.getInstance().syntaxCheckOlatLogin(login)) { - textAreaElement.setErrorKey("error.login", new String[] { String.valueOf(i + 1), login }); - importDataError = true; - break; - } } else { textAreaElement.setErrorKey("error.columncount", new String[] { String.valueOf(i + 1) }); importDataError = true; @@ -205,39 +213,33 @@ class ImportStep00 extends BasicStep { columnId++; // pwd row + pwd = null; if (canCreateOLATPassword) { if (parts.length > columnId) { - pwd = parts[columnId].trim(); - if (StringHelper.containsNonWhitespace(pwd)) { - if(pwd.startsWith(UserImportController.SHIBBOLETH_MARKER) && shibbolethModule.isEnableShibbolethLogins()) { - String authusername = pwd.substring(UserImportController.SHIBBOLETH_MARKER.length()); - Authentication auth = securityManager.findAuthenticationByAuthusername(authusername, ShibbolethDispatcher.PROVIDER_SHIB); - if(auth != null) { - String authLogin = auth.getIdentity().getName(); - if(!login.equals(authLogin)) { - textAreaElement.setErrorKey("error.shibbolet.name.inuse", new String[] { String.valueOf(i + 1), authusername }); - importDataError = true; - break; - } - } - } else if (!UserManager.getInstance().syntaxCheckOlatPassword(pwd)) { - textAreaElement.setErrorKey("error.pwd", new String[] { String.valueOf(i + 1), pwd }); - importDataError = true; - break; - } - } else { - // treat all white-space-only passwords as non-passwords. - // the user generation code below will then generate no - // authentication token for this user - pwd = null; + String trimmedPwd = parts[columnId].trim(); + // treat all white-space-only passwords as non-passwords. + // the user generation code below will then generate no + // authentication token for this user. + if (StringHelper.containsNonWhitespace(trimmedPwd)) { + pwd = trimmedPwd; } } else { textAreaElement.setErrorKey("error.columncount", new String[] { String.valueOf(i + 1) }); importDataError = true; break; } - } else { - pwd = null; + } + if(pwd != null && pwd.startsWith(UserImportController.SHIBBOLETH_MARKER) && shibbolethModule.isEnableShibbolethLogins()) { + String authusername = pwd.substring(UserImportController.SHIBBOLETH_MARKER.length()); + Authentication auth = securityManager.findAuthenticationByAuthusername(authusername, ShibbolethDispatcher.PROVIDER_SHIB); + if(auth != null) { + String authLogin = auth.getIdentity().getName(); + if(!login.equals(authLogin)) { + textAreaElement.setErrorKey("error.shibbolet.name.inuse", new String[] { String.valueOf(i + 1), authusername }); + importDataError = true; + break; + } + } } columnId++; @@ -261,11 +263,14 @@ class ImportStep00 extends BasicStep { // update existing accounts, add info message UpdateIdentity uIdentity = new UpdateIdentity(ident, pwd, lang); - idents.add(uIdentity); - updateIdents.add(uIdentity); - + importDataError = updateUserProperties(uIdentity, ident.getUser(), parts, i, columnId, importedEmails); if(importDataError) break; + importDataError = !validatePassword(pwd, uIdentity, i); + if(importDataError) break; + + idents.add(uIdentity); + updateIdents.add(uIdentity); } else { // no identity/user yet, create // check that no user with same login name is already in list @@ -278,16 +283,21 @@ class ImportStep00 extends BasicStep { } } - TransientIdentity ud = new TransientIdentity(); + TransientIdentity uIdentity = new TransientIdentity(); // insert fix fields: login, pwd, lang from above - ud.setName(login); - ud.setPassword(pwd); - ud.setLanguage(lang); - importDataError = updateUserProperties(ud, null, parts, i, columnId, importedEmails); + uIdentity.setName(login); + uIdentity.setPassword(pwd); + uIdentity.setLanguage(lang); + + importDataError = updateUserProperties(uIdentity, null, parts, i, columnId, importedEmails); + if(importDataError) break; + importDataError = !validateUsername(login, uIdentity, i); + if(importDataError) break; + importDataError = !validatePassword(pwd, uIdentity, i); if(importDataError) break; - idents.add(ud); - newIdents.add(ud); + idents.add(uIdentity); + newIdents.add(uIdentity); } } @@ -367,6 +377,30 @@ class ImportStep00 extends BasicStep { } return importDataError; } + + private boolean validatePassword(String password, Identity userIdentity, int column) { + if (StringHelper.containsNonWhitespace(password)) { + ValidationResult validationResult = passwordSyntaxValidator.validate(password, userIdentity); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + textAreaElement.setErrorKey("error.pwd", new String[] { String.valueOf(column + 1), descriptions }); + return false; + } + } + return true; + } + + private boolean validateUsername(String username, Identity userIdentity, int column) { + if (StringHelper.containsNonWhitespace(username)) { + ValidationResult validationResult = usernameSyntaxValidator.validate(username, userIdentity); + if (!validationResult.isValid()) { + String descriptions = validationResult.getInvalidDescriptions().get(0).getText(getLocale()); + textAreaElement.setErrorKey("error.login", new String[] { String.valueOf(column + 1), descriptions }); + return false; + } + } + return true; + } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { @@ -395,7 +429,13 @@ class ImportStep00 extends BasicStep { mandatoryProperties += ", " + translate(userPropertyHandler.i18nColumnDescriptorLabelKey()) + mandatoryChar; } textContainer.contextPut("mandatoryProperties", mandatoryProperties); - + + List<String> passwordRules = passwordSyntaxValidator.getAllDescriptions().stream() + .map(d -> d.getText(getLocale())) + .collect(Collectors.toList()); + textContainer.contextPut("passwordRules", passwordRules); + textContainer.contextPut("passwordIntro", translate("form.password.validation.rules", new String[] { })); + textAreaElement = uifactory.addTextAreaElement("importform", "form.importdata", -1, 10, 100, false, false, "", formLayout); textAreaElement.setMandatory(true); textAreaElement.setNotEmptyCheck("error.emptyform"); diff --git a/src/main/java/org/olat/admin/user/imp/_content/step0.html b/src/main/java/org/olat/admin/user/imp/_content/step0.html index 04c5c96c58c..332605d2729 100644 --- a/src/main/java/org/olat/admin/user/imp/_content/step0.html +++ b/src/main/java/org/olat/admin/user/imp/_content/step0.html @@ -9,10 +9,15 @@ $r.translate("formatexplanation.part2a") $r.translate("formatexplanation.part3") <p /> -$r.translate("formatexplanation.conventions") +<p> +$r.translateWithPackage("org.olat.user", "form.checkUsername") +</p> + +$r.translate("form.pwd.intro") <ul> - <li>$r.translateWithPackage("org.olat.user", "form.checkPassword")</li> - <li>$r.translateWithPackage("org.olat.user", "form.checkUsername")</li> +#foreach($passwordRule in $passwordRules) + <li>$passwordRule</li> +#end </ul> #o_togglebox_start("o_usermanagement_importexample" "$r.translate('import.example')") diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ar.properties index 55fac65a4f6..d3eb13ce449 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ar.properties @@ -7,10 +7,8 @@ error.emptyform=\u064A\u0631\u062C\u0649 \u0627\u0644\u0643\u062A\u0627\u0628\u0 error.lang=\u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0627\u0644\u0644\u063A\u0629 "{1}" \u063A\u064A\u0631 \u0635\u062D\u064A\u062D\u060C \u064A\u0631\u062D\u0649 \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0631\u0645\u0648\u0632 \u0644\u063A\u0629 \u0635\u062D\u064A\u062D\u0629. error.length=\u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0642\u064A\u0645\u0629 \u0627\u0644\u0635\u0641\u0629 "{1}" \u0628\u0647\u0627 \u0623\u0643\u062B\u0631 \u0645\u0646 127 \u062D\u0631\u0641\u0627\u064B. error.lengthorformat={2} \:{1} \u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0641\u0649 \u0627\u0644\u0639\u0645\u0648\u062F -error.login=\u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 "{1}" \u0644\u0627 \u064A\u062A\u0641\u0642 \u0645\u0639 \u0623\u0648\u0644\u0627\u062A\u060C \u064A\u0631\u062C\u0649 \u062A\u063A\u064A\u064A\u0631 \u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645. error.login.douplicate=\u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 "{1}" \u064A\u0648\u062C\u062F \u0645\u0631\u062A\u064A\u0646 \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644 \u0648\u064A\u062C\u0628 \u0623\u0646 \u064A\u0643\u0648\u0646 \u0645\u0648\u062C\u0648\u062F \u0645\u0631\u0629 \u0648\u0627\u062D\u062F\u0629 \u0641\u0642\u0637. error.mandatory=\u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0627\u0644\u0635\u0641\u0629 "{1}" \u0636\u0631\u0648\u0631\u064A\u0629. -error.pwd=\u062E\u0637\u0623 \u0641\u0649 \u0627\u0644\u062E\u0637 {0}\: \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 "{1}" \u0644\u0627 \u062A\u062A\u0641\u0642 \u0645\u0639 \u0623\u0648\u0644\u0627\u062A\u060C \u064A\u0631\u062C\u0649 \u062A\u063A\u064A\u064A\u0631 \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631. form.importdata=\u0646\u0633\u062E \u0627\u0644\u0635\u0641\u0648\u0641 \u0645\u0646 \u0627\u0643\u0633\u0644 formatexplanation.part1=<ul><br>. \u0627\u0633\u062A\u062E\u062F\u0645 \u0627\u0644\u0627\u0643\u0633\u0644 (\u0623\u0648 \u0627\u0644\u0623\u0648\u0641\u0633 \u0627\u0644\u0645\u0641\u062A\u0648\u062D) \u0637\u0628\u0642\u0627 \u0644\u0644\u0635\u0648\u0631\u0629 \u0628\u0627\u0644\u0623\u0633\u0641\u0644\u060C \u0648\u0627\u0646\u0642\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u062B\u0627\u0644 formatexplanation.part2.cancreatepassword=\u060C {0} \u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\u060C \u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631\u060C \u0627\u0644\u0644\u063A\u0629 \r\n</li> \u0639\u0646\u062F \u062A\u0631\u0643 \u062E\u0627\u0646\u0629 "\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631" \u0641\u0627\u0631\u063A\u0629 \u0641\u0625\u0646\u0647 \u064A\u062C\u0628 \u062A\u0632\u0648\u064A\u062F \u0647\u0630\u0627 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 \u0628\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 \u0644\u0627\u062D\u0642\u0627\u064B</li><li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_bg.properties index 2e25df3b601..27cacd8e20a 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_bg.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_bg.properties @@ -7,10 +7,9 @@ error.emptyform=\u041C\u043E\u043B\u044F, \u043F\u043E\u043F\u044A\u043B\u043D\u error.lang=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: \u0435\u0437\u0438\u043A\u044A\u0442 "{1}" \u0435 \u043D\u0435\u0432\u0430\u043B\u0438\u0434\u0435\u043D. \u041C\u043E\u043B\u044F, \u0438\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u0439\u0442\u0435 \u0432\u0430\u043B\u0438\u0434\u0435\u043D \u0435\u0437\u0438\u043A\u043E\u0432 \u043A\u043E\u0434. error.length=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: \u0441\u0442\u043E\u0439\u043D\u043E\u0441\u0442\u0442\u0430 \u043D\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 "{1}" \u0438\u043C\u0430 \u043F\u043E\u0432\u0435\u0447\u0435 \u043E\u0442 127 \u0437\u043D\u0430\u043A\u0430. error.lengthorformat=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0} \u0432 \u043A\u043E\u043B\u043E\u043D\u0430 {1}\: {2} -error.login=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E\u0442\u043E \u0438\u043C\u0435 "{1}" \u043D\u0435 \u0441\u044A\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0430 \u043D\u0430 \u0443\u0441\u043B\u043E\u0432\u0438\u044F\u0442\u0430 \u043D\u0430 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u0442\u0430. \u041C\u043E\u043B\u044F, \u043F\u0440\u043E\u043C\u0435\u043D\u0435\u0442\u0435 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E\u0442\u043E \u0438\u043C\u0435. +error.login=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: {1} error.login.douplicate=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: \u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E\u0442\u043E \u0438\u043C\u0435 "{1}" \u0435 \u043D\u0430\u043C\u0435\u0440\u0435\u043D\u043E \u043F\u043E\u043D\u0435 \u0434\u0432\u0430 \u043F\u044A\u0442\u0438, \u043D\u043E \u0442\u043E \u0442\u0440\u044F\u0431\u0432\u0430 \u0434\u0430 \u0435 \u0443\u043D\u0438\u043A\u0430\u043B\u043D\u043E. error.mandatory=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044A\u0442 "{1}" \u0435 \u0437\u0430\u0434\u044A\u043B\u0436\u0438\u0442\u0435\u043B\u0435\u043D. -error.pwd=\u0413\u0440\u0435\u0448\u043A\u0430 \u043D\u0430 \u0440\u0435\u0434 {0}\: \u043F\u0430\u0440\u043E\u043B\u0430\u0442\u0430 "{1}" \u043D\u0435 \u043E\u0442\u0433\u043E\u0432\u0430\u0440\u044F \u043D\u0430 \u0443\u0441\u043B\u043E\u0432\u0438\u044F\u0442\u0430 \u043D\u0430 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u0442\u0430. \u041C\u043E\u043B\u044F, \u043F\u0440\u043E\u043C\u0435\u043D\u0435\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u0430\u0442\u0430. form.importdata=\u041A\u043E\u043F\u0438\u0440\u0430\u043D\u0438 \u0440\u0435\u0434\u043E\u0432\u0435 \u043E\u0442 Excel formatexplanation.part1=\u0418\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u0439\u0442\u0435 Excel (\u0438\u043B\u0438 OpenOffice) \u0441\u043F\u043E\u0440\u0435\u0434 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435\u0442\u043E \u043F\u043E-\u0434\u043E\u043B\u0443 (\u043A\u043B\u0438\u043A\u043D\u0435\u0442\u0435 \u043D\u0430 \u043F\u0440\u0438\u043C\u0435\u0440).<br><ul> formatexplanation.part2.cancreatepassword=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E \u0438\u043C\u0435, \u043F\u0430\u0440\u043E\u043B\u0430, \u0435\u0437\u0438\u043A{0}. </li><li>\u0410\u043A\u043E \u043F\u043E\u043B\u0435\u0442\u043E "\u041F\u0430\u0440\u043E\u043B\u0430" \u043E\u0441\u0442\u0430\u043D\u0435 \u043F\u0440\u0430\u0437\u043D\u043E, \u0432\u0438\u0435 \u0442\u0440\u044F\u0431\u0432\u0430 \u0434\u0430 \u043E\u0441\u0438\u0433\u0443\u0440\u0438\u0442\u0435 \u043F\u0430\u0440\u043E\u043B\u0430 \u0437\u0430 \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u044F \u043F\u043E-\u043A\u044A\u0441\u043D\u043E.</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_cs.properties index 8153aa7dcea..da0a4a8331b 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_cs.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_cs.properties @@ -7,10 +7,9 @@ error.emptyform=Dopl\u0148te pros\u00EDm toto pole. error.lang=Chyba na \u0159\u00E1dce {0}\: jazyk "{1}" je \u0161patn\u011B. Vlo\u017Ete spr\u00E1v\u00FD k\u00F3d jazyka. error.length=Chyba na \u0159\u00E1dku {0}\: hodnota atributu "{1}" m\u00E1 v\u00EDce ne\u017E 127 znak\u016F. error.lengthorformat=Chyba na \u0159\u00E1dku {0} ve sloupci {1}\: {2} -error.login=Chyba na \u0159\u00E1dce {0}\: u\u017Eivatelsk\u00E9 jm\u00E9no "{1}" neodpov\u00EDd\u00E1 konvenc\u00EDm OLATu. Zm\u011B\u0148te ho pros\u00EDm. +error.login=Chyba na \u0159\u00E1dce {0}\: {1} error.login.douplicate=Chyba na \u0159\u00E1dku {0}\: U\u017Eivatelsk\u00E9 jm\u00E9no "{1}" bylo nalezeno alespo\u0148 dvakr\u00E1t, ale m\u00E1 b\u00FDt unik\u00E1tn\u00ED. error.mandatory=Chyba na \u0159\u00E1dku {0}\: atribut "{1}" je povinn\u00FD. -error.pwd=Chyba na \u0159\u00E1dce {0}\: heslo "{1}" neodpov\u00EDd\u00E1 konvenc\u00EDm OLATu. Zm\u011B\u0148te ho pros\u00EDm. form.importdata=\u0158\u00E1dky zkop\u00EDrovan\u00E9 z Excelu formatexplanation.part1=Pou\u017Eijte Excel (nebo OpenOffice) podle n\u00E1sleduj\u00EDc\u00EDho obr\u00E1zku (klikn\u011Bte pro uk\u00E1zku).<br><ul> formatexplanation.part2.cancreatepassword=U\u017Eivatelsk\u00E9 jm\u00E9no, heslo, jazyk{0}. </li><li>Pokud z\u016Fstane pole "Heslo" pr\u00E1zdn\u00E9 budete muset p\u0159i\u0159adit u\u017Eivateli heslo pozd\u011Bji.</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_da.properties index 4ad99b36c9f..dc201dc8348 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_da.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_da.properties @@ -3,8 +3,7 @@ error.columncount=Fejl i linie {0}\: ikke nok elementer error.email=Fejl i linie {0}\: e-mailadresse "{1}" er ugyldig. Angiv venligst en komplet og gyldig e-mailadresse. error.email.douplicate=Fejl i linie {0}\: e-mailadressen "{1}" er allerede i brug for bruger "{2}". error.lang=Fejl i linie {0}\: sproget "{1}" er ugyldigt. Brug venligst en gyldig sprogkode. -error.login=Fejl i linie {0}\: brugernavnet "{1}" overholder ikke OLAT reglerne. Tilpas venligst brugernavnet. -error.pwd=Fejl i linie {0}\: kodeordet "{1}" overholder ikke OLAT reglerne. Udskift venligst kodeordet. +error.login=Fejl i linie {0}\: {1} form.importdata=Kopierede kolonner fra Excel import.confirm={0} brugere i tabellen, {1} nye, og {2} eksisterende. <br>Vil du importere de {1} nye brugere til OLAT? import.example=Eksempel billede diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties index 0c820897012..bdf5e909a77 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties @@ -8,18 +8,18 @@ error.emptyform=Bitte f\u00FCllen Sie dieses Feld aus. error.lang=Fehler auf Zeile {0}\: die Sprache "{1}" ist ung\u00FCltig. Bitte geben Sie eine g\u00FCltige Sprache an. error.length=Fehler auf Zeile {0}\: der Wert "{1}" hat mehr als 127 Zeichen. error.lengthorformat=Fehler auf Zeile {0} in Spalte {1}\: {2} -error.login=Fehler auf Zeile {0}\: der Benutzername "{1}" entspricht nicht den OLAT-Konventionen. Bitte \u00E4ndern Sie diesen Benutzernamen. +error.login=Fehler auf Zeile {0}\: {1} error.login.douplicate=Fehler auf Zeile {0}\: Der Benutzername "{1}" ist mehrfach in der Liste vorhanden, sollte jedoch einmalig sein. error.mandatory=Fehler auf Zeile {0}\: die Angabe von "{1}" ist obligatorisch. -error.pwd=Fehler auf Zeile {0}\: das Passwort "{1}" entspricht nicht den OLAT-Konventionen. Bitte \u00E4ndern Sie dieses Passwort. +error.pwd=Fehler auf Zeile {0}\: Das Password ist nicht g\u00FCltig.{1} error.shibbolet.name.inuse=Fehler auf Zeile {0}\: dieser Shibboleth-Identifikator "{1}" wird bereits in einem bestehenden Konto benutzt. form.importdata=Kopierte Zeilen aus Excel +form.pwd.intro=Das neue Password muss folgende Kriterien erf\u00FCllen: formatexplanation.part1=Benutzen Sie Excel (oder OpenOffice) gem\u00E4ss untenstehender Abbildung (Auf Beispielabbildung klicken).<br><ul> formatexplanation.part2.cancreatepassword=Benutzername *, Passwort, Sprache{0}.</li><li>Wenn das Feld "Passwort" leer gelassen wird, m\u00FCssen Sie dem Benutzer sp\u00E4ter ein Passwort setzen.</li> formatexplanation.part2.cannotcreatepassword=Benutzername *, Sprache{0}. </li> formatexplanation.part2a=<li>Folgende Felder sind auszuf\u00FCllen (solche mit * zwingend)\: formatexplanation.part3=<li>Wenn das Feld "Sprache" leer gelassen wird, so wird die Standardsprache der OLAT-Installation verwendet.</li><li>Orientieren Sie sich in der Excel-Vorlage \u00FCber die Reihenfolge der Angaben und \u00FCber weitere konfigurationsabh\u00E4ngige Spalten. </li></ul> -formatexplanation.conventions=Richtlinien f\u00fcr Benutzername und Passwort: import.confirm=Sie m\u00F6chten {0} Benutzer importieren. Davon ist/sind {1} neu, {2} ist/sind bereits in OLAT vorhanden. Klicken Sie auf "Fertigstellen", um {1} neue Benutzer zu importieren. import.description0=Gef\u00FChrt von einem Wizard k\u00F6nnen Sie mehrere Benutzer auf einmal importieren. Sie ben\u00F6tigen dazu eine Liste mit durch Tabulator separierten Werten. import.description1=Was Sie w\u00E4hrend des Wizards erwartet\: @@ -27,7 +27,7 @@ import.description2=<i>Datenbeispiele\:</i> Sie sehen in einer Beispielabbildung import.description3=<i>Dateneingabe\:</i> Sie kopieren die Zeilen aus der Excel-Datei import.description4=<i>Vorschau der Benutzerdaten\:</i> Sie sehen, welche Benutzer bereits im System sind und welche neu angelegt werden. import.example=Beispielabbildung -import.errors=Die Benutzer wurden teilweise angelegt. Es gab Fehler w\u00e4hrend den Import Prozess: {0} +import.errors=Die Benutzer wurden teilweise angelegt. Es gab Fehler w\u00E4hrend den Import Prozess: {0} import.start=Benutzerimport starten import.success=Die neuen Benutzer wurden erfolgreich angelegt. import.user.existing.alt=Dieser Benutzer existiert bereits, er wird nicht neu angelegt @@ -40,7 +40,7 @@ step1.description=Vorschau der Benutzerdaten step1.nonewusers=Die Tabelle enth\u00E4lt keine neuen Benutzer. Sie k\u00F6nnen keine Benutzer importieren. step1.passwordEmails=Achtung: bei Passwort\u00E4nderungen f\u00FCr existierende Benutzer wird unabh\u00E4ngig von ihren Einstellungen eine E-Mail-Benachrichtigung verschickt. step1.short.descr=Vorschau -step2.description=Gruppe(n) ausw\u00e4hlen +step2.description=Gruppe(n) ausw\u00E4hlen step3.description=E-Mail-Benachrichtigung step3.short.description=E-Mail-Benachrichtigung step3.send.label= diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_el.properties index 0998df4ee96..9f82bca1a47 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_el.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_el.properties @@ -8,10 +8,9 @@ error.emptyform=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03C3\u03C5\u0 error.lang=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: \u03B7 \u03B3\u03BB\u03CE\u03C3\u03C3\u03B1 "{1}" \u03B4\u03B5\u03BD \u03B5\u03AF\u03BD\u03B1\u03B9 \u03AD\u03B3\u03BA\u03C5\u03C1\u03B7. \u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03CD\u03BC\u03B5 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03C4\u03B5 \u03AD\u03BD\u03B1\u03BD \u03AD\u03B3\u03BA\u03C5\u03C1\u03BF \u03BA\u03CE\u03B4\u03B9\u03BA\u03B1 \u03B3\u03BB\u03CE\u03C3\u03C3\u03B1\u03C2. error.length=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: \u03B7 \u03C4\u03B9\u03BC\u03AE \u03C4\u03BF\u03C5 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03B7\u03C1\u03B9\u03C3\u03C4\u03B9\u03BA\u03BF\u03CD "{1}" \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03C0\u03AC\u03BD\u03C9 \u03B1\u03C0\u03BF 127 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2. error.lengthorformat=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0} \u03C4\u03B7\u03C2 \u03C3\u03C4\u03AE\u03BB\u03B7\u03C2 {1}\: {2} -error.login=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: \u03C4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 "{1}" \u03B4\u03B5\u03BD \u03B1\u03BA\u03BF\u03BB\u03BF\u03C5\u03B8\u03B5\u03AF \u03C4\u03BF\u03C5\u03C2 \u03BA\u03B1\u03BD\u03CC\u03BD\u03B5\u03C2 \u03BF\u03BD\u03BF\u03BC\u03B1\u03C4\u03BF\u03BB\u03BF\u03B3\u03AF\u03B1\u03C2. \u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B1\u03BB\u03BB\u03AC\u03BE\u03C4\u03B5 \u03C4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7. +error.login=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: {1} error.login.douplicate=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: \u03A4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 "{1}" \u03AD\u03C7\u03B5\u03B9 \u03B2\u03C1\u03B5\u03B8\u03B5\u03AF \u03B4\u03B9\u03C2 \u03B1\u03BB\u03BB\u03AC \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03BC\u03BF\u03BD\u03B1\u03B4\u03B9\u03BA\u03CC. error.mandatory=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: \u03C4\u03BF \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03B7\u03C1\u03B9\u03C4\u03B9\u03BA\u03CC "{1}" \u03B5\u03AF\u03BD\u03B1\u03B9 \u03C5\u03C0\u03BF\u03C7\u03C1\u03B5\u03C9\u03C4\u03B9\u03BA\u03CC. -error.pwd=\u039B\u03AC\u03B8\u03BF\u03C2 \u03C3\u03C4\u03B7 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AE {0}\: \u03BF \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 "{1}" \u03B4\u03B5\u03BD \u03B1\u03BA\u03BF\u03BB\u03BF\u03C5\u03B8\u03B5\u03AF \u03C4\u03BF\u03C5\u03C2 \u03BA\u03B1\u03BD\u03CC\u03BD\u03B5\u03C2 \u03BF\u03BD\u03BF\u03BC\u03B1\u03C4\u03BF\u03BB\u03BF\u03B3\u03AF\u03B1\u03C2. \u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03BF\u03CD\u03BC\u03B5 \u03B1\u03BB\u03BB\u03AC\u03BE\u03C4\u03B5 \u03C4\u03BF\u03BD \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2. form.importdata=\u0391\u03BD\u03C4\u03B9\u03B3\u03C1\u03B1\u03BC\u03BC\u03AD\u03BD\u03B5\u03C2 \u03C3\u03B5\u03B9\u03C1\u03AD\u03C2 \u03B1\u03C0\u03CC \u03C4\u03BF Excel formatexplanation.part1=\u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03C4\u03B5 \u03C4\u03BF Excel (\u03AE \u03C4\u03BF OpenOffice) \u03CC\u03C0\u03C9\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03C6\u03B5\u03C4\u03B1\u03B9 \u03C3\u03C4\u03B7\u03BD \u03C0\u03B1\u03C1\u03B1\u03BA\u03AC\u03C4\u03C9 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1 (\u03BA\u03AC\u03BD\u03C4\u03B5 \u03BA\u03BB\u03B9\u03BA \u03C3\u03C4\u03BF \u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1).<br><ul> formatexplanation.part2.cancreatepassword=<\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7, \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2, \u03B3\u03BB\u03CE\u03C3\u03C3\u03B1{0}. </li><li>\u0386\u03BD \u03C4\u03BF \u03C0\u03B5\u03B4\u03AF\u03BF "\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2" \u03C0\u03B1\u03C1\u03B1\u03BC\u03B5\u03AF\u03BD\u03B5\u03B9 \u03BA\u03B5\u03BD\u03CC, \u03C4\u03CC\u03C4\u03B5 \u03B8\u03B1 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03B1\u03C1\u03B3\u03CC\u03C4\u03B5\u03C1\u03B1 \u03BD\u03B1 \u03BF\u03C1\u03AF\u03C3\u03B5\u03C4\u03B5 \u03B5\u03BD\u03B1\u03BD \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC \u03B3\u03B9\u03B1 \u03C4\u03BF \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03B5\u03BA\u03B5\u03AF\u03BD\u03BF\u03BD.</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties index f6835fb70fc..4db4ab026ab 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties @@ -8,13 +8,13 @@ error.emptyform=Please fill in this field. error.lang=Error in line {0}\: the language "{1}" is invalid. Please use a valid language code. error.length=Error in line {0}\: the attribute value "{1}" has more than 127 characters. error.lengthorformat=Error in line {0} in column {1}\: {2} -error.login=Error in line {0}\: the user name "{1}" does not follow OLAT conventions. Please change that user name. +error.login=Error in line {0}\: {1} error.login.douplicate=Error in line {0}\: The user name "{1}" has been found at least twice but needs to be unique. error.mandatory=Error in line {0}\: the attribute "{1}" is mandatory. -error.pwd=Error in line {0}\: the password "{1}" does not follow OLAT conventions. Please change this password. +error.pwd=Error in line {0}\: the password is not valid.{1} error.shibbolet.name.inuse=Error in line {0}\: this shibboleth identifier "{1}" is already in use in an existing account. form.importdata=Copied rows from Excel -formatexplanation.conventions=Rules for username and password\: +form.pwd.intro=The new password must meet the following criteria: formatexplanation.part1=Use Excel (or OpenOffice) according to the image below (click on example).<br><ul> formatexplanation.part2.cancreatepassword=User name *, password, language{0}. </li><li>If the field "Password" remains empty you will have to provide that user with a password later on.</li> formatexplanation.part2.cannotcreatepassword=User name *, language{0}. </li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_es.properties index 8f4ec4c5b89..310094cb240 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_es.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_es.properties @@ -7,10 +7,9 @@ error.emptyform=Por favor, complete este campo. error.lang=Error en la l\u00EDnea {0}\: el idioma "{1}" no es v\u00E1lido. Por favor utiliza un c\u00F3digo de idioma v\u00E1lido. error.length=Error en la l\u00EDnea {0}\: el valor del atributo "{1}" tiene m\u00E1s de 127 caracteres. error.lengthorformat=Error en la l\u00EDnea {0} en columna {1}\: {2} -error.login=Error en la l\u00EDnea {0}\: el nombre de usuario "{1}" no cumple las convenciones de OLAT. Por favor cambia el nombre de usuario. +error.login=Error en la l\u00EDnea {0}\: {1} error.login.douplicate=Error en la l\u00EDnea {0}\: el nombre de usuario "{1}" se ha encontrado por lo menos dos veces, pero debe ser \u00FAnico. error.mandatory=Error en la l\u00EDnea {0}\: el atributo "{1}" es obligatorio. -error.pwd=Error en la l\u00EDnea {0}\: la contrase\u00F1a "{1}" no cumple las convenciones de OLAT. Por favor cambia la contrase\u00F1a. form.importdata=Filas copiadas de Excel formatexplanation.part1=Usar Excel (o OpenOffice), como mostrado en la siguiente imagen (click en el ejemplo).<br><ul> formatexplanation.part2.cancreatepassword=Nombre de usuario, contrase\u00F1a, idioma{0}. </li><li>Si el campo "Contrase\u00F1a" permanece vac\u00EDo tendr\u00E1 que poner una contrase\u00F1a m\u00E1s adelante.</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fa.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fa.properties index a8078d62870..e7348ed3411 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fa.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fa.properties @@ -1,13 +1,4 @@ #Mon Mar 02 09:54:12 CET 2009 -error.columncount=Error in line {0}\: not enough elements -error.email=Error in line {0}\: the e-mail "{1}" is invalid. Please indicate a complete and valid e-mail address. -error.email.douplicate=Error in line {0}\: the e-mail "{1}" is already used by user "{2}". -error.lang=Error in line {0}\: the language "{1}" is invalid. Please use a valid language code. -error.login=Error in line {0}\: the user name "{1}" does not follow OLAT conventions. Please change that user name. -error.pwd=Error in line {0}\: the password "{1}" does not follow OLAT conventions. Please change this password. -form.importdata=Copied columns from Excel -import.confirm={0} users in the table, {1} new, and {2} existing. <br>Do you want to import the new {1} users into OLAT? -import.example=Example image import.success=\u06A9\u0627\u0631\u0628\u0631 \u062C\u062F\u06CC\u062F \u0628\u0627 \u0645\u0648\u0641\u0642\u06CC\u062A \u0627\u06CC\u062C\u0627\u062F \u0634\u062F. step3.send.label= submit.import=\u0630\u062E\u06CC\u0631\u0647 diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fr.properties index 309f2470636..7b3aa1af682 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_fr.properties @@ -8,13 +8,11 @@ error.emptyform=Le formulaire ne peut pas \u00EAtre vide. error.lang=Erreur \u00E0 la ligne {0}\: la langue "{1}" n'est pas valable. Veuillez indiquer une langue admise. error.length=Erreur \u00E0 la ligne {0}\: la valeur "{1}" contient plus que 127 signes. error.lengthorformat=Erreur \u00E0 la ligne {0} dans la colonne {1}\: {2} -error.login=Erreur \u00E0 la ligne {0}\: le nom d'utilisateur "{1}" ne corrrespond pas aux conventions d'OLAT. Veuillez modifier ce nom d'utilisateur. +error.login=Erreur \u00E0 la ligne {0}\: {1} error.login.douplicate=Erreur \u00E0 la ligne {0}\: le nom d'utilisateur "{1}" est contenu plusieurs fois dans la liste, il doit cependant \u00EAtre unique. error.mandatory=Erreur \u00E0 la ligne {0}\: l'indication de "{1}" est obligatoire. -error.pwd=Erreur \u00E0 la ligne {0}\: le mot de passe "{1}" ne corrrespond pas aux conventions d'OLAT. Veuillez modifier ce mot de passe. error.shibbolet.name.inuse=Erreur ligne {0}\: l'identifiant Shibbolet "{1}" est d\u00E9j\u00E0 utilis\u00E9 par un compte existant. form.importdata=Colonnes copi\u00E9es d'Excel -formatexplanation.conventions=R\u00E8gles pour le nom d'utilisateur et le mot de passe\: formatexplanation.part1=Utilisez Excel (ou OpenOffice), conform\u00E9ment \u00E0 l'illustration ci-dessous. (Cliquez sur la reproduction d'exemple).<br><ul> formatexplanation.part2.cancreatepassword=<li>Les colonnes suivantes sont obligatoires\: Login, mot de passe, langue.</li><li>La colonne avec le mot de passe peut \u00EAtre vide.</li> formatexplanation.part2.cannotcreatepassword=<li>Les colonnes suivantes sont obligatoires\: Login, mot de passe. </li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_it.properties index eb0df1bb8d7..18de23f2fe0 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_it.properties @@ -8,13 +8,11 @@ error.emptyform=Completi questo formulario, p.f. error.lang=Errore alla righa {0}\: la lingua "{1}" non \u00E8 valida. Inserisca una lingua valida, p.f. error.length=Errore alla righa {0}\: il valore "{1}" ha pi\u00F9 di 127 segni. error.lengthorformat=Errore alla righa {0} nella colonna {1}\: {2} -error.login=Errore alla righa {0}\: il nome d'utente "{1}" non \u00E8 adeguato alle convenzioni OLAT. Lo modifichi, p.f. +error.login=Errore alla righa {0}\: {1} error.login.douplicate=Errore alla righa {0}\: il nome d'utente "{1}" \u00E8 gi\u00E0 presente pi\u00F9 volte nella lista, dovrebbe per\u00F2 esserci solo una volta. error.mandatory=Errore alla righa {0}\: indicare "{1}" \u00E8 obbligatorio. -error.pwd=Errore alla righa {0}\: la password "{1}" non \u00E8 adeguata alle convenzioni OLAT. La modifichi, p.f. error.shibbolet.name.inuse=Errore nella linea {0}\: questo identificatore shibboleth "{1}" \u00E8 gi\u00E0 in uso in un account esistente. form.importdata=Righe copiate da Excel -formatexplanation.conventions=Regole per nome utente e password\: formatexplanation.part1=Utilizzi Excel (oppure OpenOffice) conformemente all'illustrazione sottostante (cliccare sull'immagine).<br><ul> formatexplanation.part2.cancreatepassword=Nome d'utente *, password, lingua{0}.</li><li>La casella della password pu\u00F2 restare vuota\: in tal caso dovr\u00E0 dare una password all'utente in un secondo tempo</li> formatexplanation.part2.cannotcreatepassword=\: Nome d'utente *, lingua{0}. </li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_jp.properties index 3eb8fde7168..d4ae30504fc 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_jp.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_jp.properties @@ -7,10 +7,9 @@ error.emptyform=\u3053\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u5165\u529B\u30 error.lang={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: \u8A00\u8A9E "{1}" \u304C\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u6709\u52B9\u306A\u8A00\u8A9E\u30B3\u30FC\u30C9\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002 error.length={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: \u5C5E\u6027\u5024 "{1}" \u306B127\u6587\u5B57\u4EE5\u4E0A\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 error.lengthorformat={1} \u30AB\u30E9\u30E0\u5185\u306E {0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: {2} -error.login={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: \u30E6\u30FC\u30B6\u540D "{1}" \u306F\u3001OLAT\u306E\u30EB\u30FC\u30EB\u306B\u5F93\u3063\u3066\u3057\u307E\u305B\u3093\u3002\u30E6\u30FC\u30B6\u540D\u3092\u5909\u66F4\u3057\u3066\u304F\u3060\u3055\u3044\u3002 +error.login={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: {1} error.login.douplicate={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: \u30E6\u30FC\u30B6\u540D "{1}" \u304C2\u56DE\u4EE5\u4E0A\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\u30E6\u30FC\u30B6\u540D\u306F\u3001\u30E6\u30CB\u30FC\u30AF (\u56FA\u6709) \u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 error.mandatory={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: \u5C5E\u6027 "{1}" \u306F\u3001\u5FC5\u9808\u9805\u76EE\u3067\u3059\u3002 -error.pwd={0} \u884C\u76EE\u306B\u30A8\u30E9\u30FC\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\: \u30D1\u30B9\u30EF\u30FC\u30C9 "{1}" \u306F\u3001OLAT\u306E\u30EB\u30FC\u30EB\u306B\u5F93\u3063\u3066\u3057\u307E\u305B\u3093\u3002\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5909\u66F4\u3057\u3066\u304F\u3060\u3055\u3044\u3002 form.importdata=Excel\u304B\u3089\u30B3\u30D4\u30FC\u3055\u308C\u305F\u884C formatexplanation.part1=\u4EE5\u4E0B\u306E\u30A4\u30E1\u30FC\u30B8\u306B\u5F93\u3063\u3066\u3001Excel (\u307E\u305F\u306FOpenOffice)\u3092\u4F7F\u7528\u3057\u307E\u3059 (\u30B5\u30F3\u30D7\u30EB\u3092\u30AF\u30EA\u30C3\u30AF)\u3002<br /><ul> formatexplanation.part2.cannotcreatepassword=\u30E6\u30FC\u30B6\u540D\u3001\u8A00\u8A9E\u3000{0}</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_lt.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_lt.properties index 7357fc3e36e..f26b7291fa2 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_lt.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_lt.properties @@ -3,8 +3,7 @@ error.columncount=Klaida eilut\u0117je {0}\: nepakankamas kiekis element\u0173 error.email=Klaida eilut\u0117je {0}\: el. pa\u0161tas "{1}" neteisingas. Pra\u0161ome nurodyti piln\u0105 ir galiojant\u012F el. pa\u0161to adres\u0105. error.email.douplicate=Klaida eilut\u0117je {0}\: el. pa\u0161tas adresas "{1}" jau yra naudojamas vartotojo "{2}". error.lang=Klaida eilut\u0117je {0}\: kalba "{1}" yra neteisinga. Pra\u0161ome naudoti galiojant\u012F kalbos kod\u0105. -error.login=Klaida eilut\u0117je {0}\: naudotojo vardas "{1}" ne\u012Feina \u012F OLAT konvencijas. Pra\u0161ome pasikeisti vartotojo vard\u0105. -error.pwd=Klaida eilut\u0117je {0}\: slapta\u017Eodis "{1}" ne\u012Feina \u012F OLAT konvencijas. Pra\u0161ome pasikeisti slapta\u017Eod\u012F. +error.login=Klaida eilut\u0117je {0}\: {1} form.importdata=Nukopijuoti stulpeliai i\u0161 Excel import.confirm={0}vartotojai lentel\u0117je,{1} naujas, ir {2}egzistuojantis. <br>Ar norite \u012Fvesti naujus {1} vartotojus \u012F OLAT? import.example=Pavyzdinis vaizdas diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_nl_NL.properties index a210a923e02..4d34c6a5349 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_nl_NL.properties @@ -8,10 +8,9 @@ error.emptyform=Gelieve dit veld in te vullen. error.lang=Fout in lijn {0}\: de taal "{1}" is ongeldig. Gelieve een geldige taalcode te gebruiken. error.length=Fout in lijn {0}\: De attributenwaarde "{1}" bevat meer dan 127 tekens. error.lengthorformat=Fout in lijn {0} in kolum {1}\: {2} -error.login=Fout in lijn {0}\: De gebruikersnaam "{1}" voldoet niet aan de OLAT conventies. Gelieve die gebruikersnaam te veranderen. +error.login=Fout in lijn {0}\: {1} error.login.douplicate=Fout in lijn {0}\: De gebruikersnaam "{1}" werd tenminste twee keer gevonden maar moet uniek zijn. error.mandatory=Fout in lijn {0}\: Het attribuut "{1}" is verplicht. -error.pwd=Fout in lijn {0}\: Het wachtwoord "{1}" voldoet niet aan de OLAT conventies. Gelieve dit wachtwoord te veranderen. form.importdata=Gekopieerde rijen uit Excel formatexplanation.part1=Gebruik Excel (of OpenOffice) volgens de onderstaande afbeelding (klik op voorbeeld).<br><ul> formatexplanation.part2.cancreatepassword=Gebruikersnaam *, wachtwoord, taal{0}. </li><li>Als het veld "Wachtwoord" leeg blijft, moet u die gebruiker later voorzien van een wachtwoord.</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pl.properties index a6896d838d3..4204bc25d26 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pl.properties @@ -8,12 +8,10 @@ error.emptyform=Ten formularz nie mo\u017Ce by\u0107 pusty. error.lang=B\u0142\u0105d w linii {0}\: j\u0119zyk "{1}" nie jest warto\u015Bci\u0105 poprawn\u0105. U\u017Cyj poprawnego kodu j\u0119zyka, np. pl error.length=B\u0142\u0105d w linii {0}\: warto\u015Bc atrybutu "{1}" ma wi\u0119cej niz 127 znak\u00F3w. error.lengthorformat=B\u0142\u0105d w linii {0} w kolumnie {1}\: {2} -error.login=B\u0142\u0105d w linii {0}\: nazwa u\u017Cytkownika "{1}" nie jest zgodna z konwencj\u0105 OLAT. +error.login=B\u0142\u0105d w linii {0}\: {1} error.login.douplicate=B\u0142\u0105d w linii {0}\: nazwa u\u017Cytkownika "{1}" zosta\u0142a dwukrotnie odnaleziona, a musi byc niepowtarzalna. error.mandatory=B\u0142\u0105d w linii {0}\: atrybut "{1}" jest obowi\u0105zkowy. -error.pwd=B\u0142\u0105d w linii {0}\: has\u0142o "{1}" nie jest zgodna z konwencj\u0105 OLAT. form.importdata=Kolumny skopiowane z Excel-a -formatexplanation.conventions=Zasady dla nazwy u\u017Cytkownika i has\u0142a\: formatexplanation.part1=U\u017Cyj Excel-a (lub OpenOffice-a) tak jak pokazano na poni\u017Cszym rysunku. <br><ul> formatexplanation.part2.cancreatepassword=<li>Te pola s\u0105 obowi\u0105zkowe\: nazwa u\u017Cytkownika, has\u0142o, j\u0119zyk. Kolumna "has\u0142o" mo\u017Ce by\u0107 pusta. formatexplanation.part2.cannotcreatepassword=<li>Te pola s\u0105 obowi\u0105zkowe\: login, j\u0119zyk. diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_BR.properties index 05024e496a0..a373217b830 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_BR.properties @@ -8,13 +8,11 @@ error.emptyform=Favor complete esse campo. error.lang=Erro na linha {0}\: o idioma "{1}" \u00E9 inv\u00E1lido. Favor usar um c\u00F3digo de linguagem v\u00E1lido. error.length=Erro na linha {0}\: o valor atribu\u00EDdo "{1}" tem mais que 127 caract\u00E9res. error.lengthorformat=Erro na linha {0} na coluna {1}\: {2} -error.login=Erro na linha {0}\: o nome de usu\u00E1rio "{1}" n\u00E3o segue as conven\u00E7\u00F5es do OLAT. Favor mudar este nome de usu\u00E1rio. +error.login=Erro na linha {0}\: {1} error.login.douplicate=Erro na linha {0}\: O usu\u00E1rio "{1}" foi encontrado pelo menos duas vezes mas precisa ser \u00FAnico. error.mandatory=Erro na linha {0}\: a informa\u00E7\u00E3o "{1}" \u00E9 obrigat\u00F3rio. -error.pwd=Erro na linha {0}\: a senha "{1}" n\u00E3o segue as conven\u00E7\u00F5es do OLAT. Favor mudar esta senha. error.shibbolet.name.inuse=Erro na linha {0}\: este identificador shibboleth "{1}" j\u00E1 est\u00E1 em uso em uma conta existente. form.importdata=Colunas copiadas do Excel -formatexplanation.conventions=Regras para nome de usu\u00E1rio e senha\: formatexplanation.part1=Use o Excel (ou OpenOffice) de acordo com a imagem abaixo (clique no exemplo).<br><ul> formatexplanation.part2.cancreatepassword=Usu\u00E1rio, senha, idioma{0}. </li><li>Se o campo "senha" permanecer vazio voc\u00EA ir\u00E1 precisar fornecer a aquele usu\u00E1rio uma senha posteriormente.</li> formatexplanation.part2.cannotcreatepassword=User name, language{0}. </li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_PT.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_PT.properties index f930c6b0300..7fa9f66ac1a 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_PT.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_pt_PT.properties @@ -3,8 +3,7 @@ error.columncount=Erro na linha {0}\: elementos n\u00E3o suficientes error.email=Erro na linha {0}\: o e-mail "{1}" \u00E9 inv\u00E1lido. Favor indicar um endere\u00E7o de e-mail completo e v\u00E1lido. error.email.douplicate=Erro na linha {0}\: o e-mail "{1}" j\u00E1 \u00E9 usado pelo usu\u00E1rio "{2}". error.lang=Erro na linha {0}\: o idioma "{1}" \u00E9 inv\u00E1lido. Favor usar um c\u00F3digo de linguagem v\u00E1lido. -error.login=Erro na linha {0}\: o nome de usu\u00E1rio "{1}" n\u00E3o segue as conven\u00E7\u00F5es do OLAT. Favor mudar este nome de usu\u00E1rio. -error.pwd=Erro na linha {0}\: a senha "{1}" n\u00E3o segue as conven\u00E7\u00F5es do OLAT. Favor mudar esta senha. +error.login=Erro na linha {0}\: {1} form.importdata=Colunas copiadas do Excel import.confirm={0} usu\u00E1rios na tabela , {1} novo, e {2} existente. <br>Voc\u00EA quer importar os novos {1} usu\u00E1rios do OLAT? import.example=Imagem exemplo diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ru.properties index 79d0e95a646..9c9aac938b6 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ru.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_ru.properties @@ -3,8 +3,7 @@ error.columncount=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440 error.email=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440\u043E\u043A\u0435 {0}\: email "{1}" \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D. \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043F\u043E\u043B\u043D\u044B\u0439 \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 e-mail \u0430\u0434\u0440\u0435\u0441, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430. error.email.douplicate=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440\u043E\u043A\u0435 {0}\: e-mail "{1}" \u0443\u0436\u0435 \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044E "{2}". error.lang=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440\u043E\u043A\u0435 {0}\: \u044F\u0437\u044B\u043A "{1}" \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D. \u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u0438\u043C\u0435\u044E\u0449\u0438\u0439\u0441\u044F \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u0435 \u044F\u0437\u044B\u043A. -error.login=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440\u043E\u043A\u0435 {0}\: \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F "{1}" \u043D\u0435 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430\u043C \u0441\u0438\u0441\u0442\u0435\u043C\u044B OLAT. \u0418\u0437\u043C\u0435\u043D\u0438\u0442\u0435 \u0434\u0430\u043D\u043D\u043E\u0435 \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430. -error.pwd=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440\u043E\u043A\u0435 {0}\: \u043F\u0430\u0440\u043E\u043B\u044C "{1}" \u043D\u0435 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430\u043C \u0441\u0438\u0441\u0442\u0435\u043C\u044B OLAT. \u0418\u0437\u043C\u0435\u043D\u0438\u0442\u0435 \u0434\u0430\u043D\u043D\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C, \u043F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430. +error.login=\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0441\u0442\u0440\u043E\u043A\u0435 {0}\: {1} form.importdata=\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0441\u0442\u043E\u043B\u0431\u0446\u044B \u0438\u0437 Excel import.confirm={0} \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u0435\u0439 \u0432 \u0442\u0430\u0431\u043B\u0438\u0446\u0435, \u0438\u0437 \u043A\u043E\u0442\u043E\u0440\u044B\u0445 {1} \u043D\u043E\u0432\u044B\u0445, \u0438 {2} \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0442 \u0432 \u0441\u0438\u0441\u0442\u0435\u043C\u0435 OLAT. <br>\u0425\u043E\u0442\u0438\u0442\u0435 \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C {1} \u043D\u043E\u0432\u044B\u0445 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u0435\u0439 \u0432 OLAT? import.example=\u0418\u043B\u043B\u044E\u0441\u0442\u0440\u0430\u0446\u0438\u044F - \u043F\u0440\u0438\u043C\u0435\u0440 diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_sq.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_sq.properties index 91709725355..75816638b31 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_sq.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_sq.properties @@ -3,8 +3,6 @@ error.columncount=Gabim n\u00EB rreshtin {0}\: nuk ka elemente t\u00EB mjaftuesh error.email=Gabim n\u00EB rreshtin {0}\: e-posta "{1}" \u00EBsht\u00EB e pavlefshme. Ju lutemi shkruani nj\u00EB adres\u00EB t\u00EB plot\u00EB dhe t\u00EB vlefshme t\u00EB e-post\u00EBs. error.email.douplicate=Gabim n\u00EB rreshtin {0}\: e-posta "{1}" tanim\u00EB \u00EBsht\u00EB p\u00EBrdorur nga shfryt\u00EBzuesi "{2}". error.lang=Gabim n\u00EB rreshtin {0}\: gjuha \u00EBsht\u00EB "{1}" e pavlefshme. Ju lutemi p\u00EBrdorni nj\u00EB kod t\u00EB vlefsh\u00EBm t\u00EB gjuh\u00EBs. -error.login={0}\: the user name "{1}" nuk ndjek konventat e OLAT-it. Ju lutemi nd\u00EBrro emrin e shfryt\u00EBzuesit. -error.pwd=Gabim n\u00EB rreshtin {0}\: fjal\u00EBkalimi "{1}" nuk ndjek konventat e OLAT-it. Ju lutemi nd\u00EBrro k\u00EBt\u00EB fjalkalim. form.importdata=Kolona t\u00EB kopjuara nga Exceli import.confirm={0} shfryt\u00EBzues n\u00EB tabel\u00EBn, {1} t\u00EB rinj\u00EB dhe {2} q\u00EB ekzistojn\u00EB. <br>A doni t'i importoni shfryt\u00EBzuesit {1} e rinj\u00EB n\u00EB OLAT? import.example=Imazh shembull diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_CN.properties index 53291db4c3a..b839c86d22e 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_CN.properties @@ -7,10 +7,9 @@ error.emptyform=\u8BF7\u586B\u5165\u6B64\u5B57\u6BB5\u3002 error.lang=\u5728\u7B2C{0}\u884C\u4E2D\u51FA\u9519\uFF1A\u8BED\u8A00\u201C{1}\u201D\u65E0\u6548\u3002\u8BF7\u4F7F\u7528\u4E00\u4E2A\u6709\u6548\u7684\u8BED\u8A00\u7F16\u7801\u3002 error.length=\u9519\u8BEF\u53D1\u751F\u4E8E{0}\u884C\:\u5C5E\u6027\u503C"{1}"\u8D85\u51FA127\u4E2A\u5B57\u7B26\u3002 error.lengthorformat=\u53D1\u751F\u4E8E{0}\u884C{1}\u5217\u7684\u9519\u8BEF\uFF1A{2} -error.login=\u5728\u7B2C{0}\u884C\u4E2D\u51FA\u9519\uFF1A\u7528\u6237\u540D\u201C{1}\u201D\u672A\u9075\u5FAAOLAT\u7684\u7EA6\u5B9A\uFF0C\u8BF7\u4FEE\u6539\u8BE5\u7528\u6237\u540D +error.login=\u5728\u7B2C{0}\u884C\u4E2D\u51FA\u9519\uFF1A{1} error.login.douplicate=\u9519\u8BEF\u53D1\u751F\u4E8E{0}\u884C\uFF1A\u7528\u6237\u540D"{1}"\u81F3\u5C11\u5DF2\u7ECF\u51FA\u73B0\u4E24\u6B21\uFF0C\u7528\u6237\u540D\u5FC5\u987B\u552F\u4E00\uFF01 error.mandatory=\u9519\u8BEF\u53D1\u751F\u4E8E{0}\u884C\uFF1A\u5C5E\u6027"{1}"\u662F\u4EBA\u5DE5\u64CD\u4F5C\u7684\u3002 -error.pwd=\u5728\u7B2C{0}\u884C\u4E2D\u51FA\u9519\uFF1A\u5BC6\u7801\u201C{1}\u201D\u672A\u9075\u5FAAOLAT\u7684\u7EA6\u5B9A\uFF0C\u8BF7\u6539\u53D8\u8BE5\u5BC6\u7801 form.importdata=\u4ECEExcel\u4E2D\u590D\u5236 formatexplanation.part1=\u6839\u636E\u4E0B\u9762\u7684\u56FE\u4F8B\u4F7F\u7528Excel(\u6216\u8005OpenOffice)\u5BFC\u5165\u7528\u6237\u6570\u636E<br><ul> formatexplanation.part2.cancreatepassword=\u7528\u6237\u540D\uFF0C\u5BC6\u7801\uFF0C\u4F7F\u7528\u8BED\u8A00{0}.</li><li>\u5982\u679C\u201C\u5BC6\u7801\u201D\u90E8\u5206\u4ECD\u7136\u662F\u7A7A\u7684\uFF0C\u90A3\u4E48\u4EE5\u540E\u60A8\u4E5F\u8981\u63D0\u4F9B\u7528\u6237\u7684\u5BC6\u7801.</li> diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_TW.properties index 75ac8474224..f2e74315c31 100644 --- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_zh_TW.properties @@ -7,10 +7,9 @@ error.emptyform=\u9019\u500B\u8868\u55AE\u4E0D\u80FD\u7A7A\u767D\u3002 error.lang=\u932F\u8AA4\u5728\u7B2C {0} \u884C\uFF1A\u8A9E\u8A00 "{1}" \u662F\u7121\u6548\u7684\u3002\u8ACB\u4F7F\u7528\u4E00\u500B\u6709\u6548\u7684\u8A9E\u8A00\u4EE3\u78BC\u3002 error.length=\u932F\u8AA4\u5728\u7B2C {0} \u884C\: \u5C6C\u6027\u503C "{1}" \u8D85\u904E 127 \u500B\u5B57\u5143\u3002 error.lengthorformat=\u932F\u8AA4\u5728\u7B2C {0} \u884C\u7B2C {1} \u6B04\: {2} -error.login=\u932F\u8AA4\u5728\u7B2C {0} \u884C\uFF1A\u4F7F\u7528\u8005\u540D\u7A31 "{1}" \u672A\u9075\u5FAA OLAT \u7684\u898F\u5B9A\u3002\u8ACB\u66F4\u6539\u8A72\u4F7F\u7528\u8005\u540D\u7A31\u3002 +error.login=\u932F\u8AA4\u5728\u7B2C {0} \u884C\uFF1A{1} error.login.douplicate=\u932F\u8AA4\u5728\u7B2C {0} \u884C\: \u4F7F\u7528\u8005\u540D\u7A31 "{1}" \u91CD\u8907\uFF0C\u5FC5\u9808\u552F\u4E00\u3002 error.mandatory=\u932F\u8AA4\u5728\u7B2C {0} \u884C\: \u5C6C\u6027 "{1}" \u662F\u5FC5\u586B\u7684\u3002 -error.pwd=\u932F\u8AA4\u5728\u7B2C {0} \u884C\uFF1A\u5BC6\u78BC "{1}" \u672A\u9075\u5FAA OLAT \u7684\u898F\u5B9A\u3002\u8ACB\u66F4\u6539\u8A72\u5BC6\u78BC\u3002 form.importdata=\u5F9E Excel \u8907\u88FD\u8CC7\u6599\u5217 formatexplanation.part1=\u4F9D\u7167\u5E95\u4E0B\u7684\u5716\u7247\uFF08\u7528\u6ED1\u9F20\u5728\u5716\u4F8B\u4E0A\u9EDE\u4E00\u4E0B\uFF09\u4F7F\u7528 Excel (\u6216 OpenOffice)\u3002<br><ul> formatexplanation.part2.cancreatepassword=\u4F7F\u7528\u8005\u540D\u7A31, \u5BC6\u78BC, \u8A9E\u8A00{0}\u3002 </li><li>\u5982\u679C\u6B04\u4F4D "\u5BC6\u78BC" \u4FDD\u6301\u7A7A\u767D\uFF0C\u4E4B\u5F8C\u60A8\u5FC5\u9808\u63D0\u4F9B\u8A72\u4F7F\u7528\u8005\u4E00\u500B\u5BC6\u78BC\u3002</li> diff --git a/src/main/java/org/olat/basesecurity/BaseSecurity.java b/src/main/java/org/olat/basesecurity/BaseSecurity.java index 7703b432b14..a91cad67e00 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurity.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurity.java @@ -351,10 +351,12 @@ public interface BaseSecurity { * Check if the password is allowed. * * @param identity + * @param provider * @param password + * @param historyLength * @return */ - public boolean checkCredentialHistory(Identity identity, String provider, String password); + public boolean checkCredentialHistory(Identity identity, String provider, String password, int historyLength); /** * diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java index 9bf9810d7b6..e35c7ec98eb 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java @@ -955,9 +955,8 @@ public class BaseSecurityManager implements BaseSecurity, UserDataDeletable { } @Override - public boolean checkCredentialHistory(Identity identity, String provider, String password) { + public boolean checkCredentialHistory(Identity identity, String provider, String password, int historyLength) { boolean ok = true; - int historyLength = loginModule.getPasswordHistory(); if(historyLength > 0) { List<AuthenticationHistory> credentialHistory = authenticationHistoryDao .loadHistory(identity, provider, 0, historyLength); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java index 95d18e6ca62..34d2116e4b1 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormItemImpl.java @@ -623,7 +623,7 @@ public abstract class FormItemImpl implements FormItem, InlineElement { } /** - * @see org.olat.core.gui.components.form.flexible.FormComponent#validate(java.util.List) + * @see org.olat.core.gui.components.form.flexible.FormComponent#validate(java.util.List, Identity) */ @Override public void validate(List<ValidationStatus> validationResults) { diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/JSDateChooser.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/JSDateChooser.java index ceca30d10db..9f8a5abef78 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/JSDateChooser.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/JSDateChooser.java @@ -123,7 +123,7 @@ public class JSDateChooser extends TextElementImpl implements DateChooser { } /** - * @see org.olat.core.gui.components.form.flexible.elements.AbstractTextElement#validate(java.util.List) + * @see org.olat.core.gui.components.form.flexible.elements.AbstractTextElement#validate(java.util.List, Identity) */ @Override public void validate(List<ValidationStatus> validationResults) { diff --git a/src/main/java/org/olat/course/nodes/projectbroker/CustomfieldsFormController.java b/src/main/java/org/olat/course/nodes/projectbroker/CustomfieldsFormController.java index 0555e483717..d4a3aa9ef61 100644 --- a/src/main/java/org/olat/course/nodes/projectbroker/CustomfieldsFormController.java +++ b/src/main/java/org/olat/course/nodes/projectbroker/CustomfieldsFormController.java @@ -90,7 +90,7 @@ public class CustomfieldsFormController extends FormBasicController { } /** - * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest) + * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest, Identity) */ public boolean validate() { return true; diff --git a/src/main/java/org/olat/course/nodes/projectbroker/OptionsFormController.java b/src/main/java/org/olat/course/nodes/projectbroker/OptionsFormController.java index 65ca66c7eea..dedefe10d55 100644 --- a/src/main/java/org/olat/course/nodes/projectbroker/OptionsFormController.java +++ b/src/main/java/org/olat/course/nodes/projectbroker/OptionsFormController.java @@ -73,7 +73,7 @@ public class OptionsFormController extends FormBasicController { } /** - * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest) + * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest, Identity) */ public boolean validate() { return true; diff --git a/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java b/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java index 67588bc280d..14aeb3f3683 100644 --- a/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java +++ b/src/main/java/org/olat/course/nodes/st/EditScoreCalculationEasyForm.java @@ -235,7 +235,7 @@ public class EditScoreCalculationEasyForm extends FormBasicController { } /** - * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest) + * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest, Identity) */ @Override public boolean validateFormLogic(UserRequest ureq) { diff --git a/src/main/java/org/olat/login/LoginModule.java b/src/main/java/org/olat/login/LoginModule.java index 02246733164..5c767b5cec3 100644 --- a/src/main/java/org/olat/login/LoginModule.java +++ b/src/main/java/org/olat/login/LoginModule.java @@ -26,14 +26,17 @@ package org.olat.login; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.apache.logging.log4j.Logger; import org.olat.basesecurity.OrganisationRoles; import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.id.Roles; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.StartupException; import org.olat.core.logging.Tracing; import org.olat.core.util.Encoder; @@ -65,7 +68,26 @@ public class LoginModule extends AbstractSpringModule { OrganisationRoles.poolmanager, OrganisationRoles.linemanager }; + public static final String DISABLED = "disabled"; + public static final String FORBIDDEN = "forbiddden"; + public static final String AT_LEAST_1 = "atLeast1"; + public static final String AT_LEAST_2 = "atLeast2"; + public static final String AT_LEAST_3 = "atLeast3"; + public static final String VALIDATE_SEPARATELY = "validateSeparately"; + + private static final String USERNAME_REGEX = "username.regex"; private static final String CHANGE_ONCE = "password.change.once"; + private static final String MIN_LENGTH = "password.min.length"; + private static final String MAX_LENGTH = "password.max.length"; + private static final String LETTERS = "password.letters"; + private static final String LETTERS_UPPER = "password.letters.upper"; + private static final String LETTERS_LOWER = "password.letters.lower"; + private static final String DIGITS_SPECIALS = "password.digits.specials"; + private static final String DIGITS = "password.digits"; + private static final String SPECIALS = "password.specials"; + private static final String FORBIDDEN_USERNAME = "password.forbidden.username"; + private static final String FORBIDDEN_FIRSTNAME = "password.forbidden.firstname"; + private static final String FORBIDDEN_LASTNAME = "password.forbidden.lastname"; private static final String MAX_AGE = "password.max.age"; private static final String MAX_AGE_AUTHOR = "password.max.age.author"; private static final String MAX_AGE_GROUPMANAGER = "password.max.age.groupmanager"; @@ -91,6 +113,10 @@ public class LoginModule extends AbstractSpringModule { private int attackPreventionMaxAttempts; @Value("${login.AttackPreventionTimeoutmin:5}") private int attackPreventionTimeout; + + @Value("${username.regex}") + private String usernameRegex; + private Pattern usernamePattern; @Value("${password.change.valid.hours.gui}") private Integer validUntilHoursGui; @@ -100,6 +126,29 @@ public class LoginModule extends AbstractSpringModule { @Value("${password.change.once:false}") private boolean passwordChangeOnce; + @Value("${password.min.length}") + private int passwordMinLength; + @Value("${password.max.length}") + private int passwordMaxLength; + @Value("${password.letters}") + private String passwordLetters; + @Value("${password.letters.uppercase}") + private String passwordLettersUppercase; + @Value("${password.letters.lowercase}") + private String passwordLettersLowercase; + @Value("${password.digits.special.signs}") + private String passwordDigitsAndSpecialSigns; + @Value("${password.digits}") + private String passwordDigits; + @Value("${password.special.signs}") + private String passwordSpecialSigns; + @Value("${password.forbidden.username}") + private boolean passwordUsernameForbidden; + @Value("${password.forbidden.firstname}") + private boolean passwordFirstnameForbidden; + @Value("${password.forbidden.lastname}") + private boolean passwordLastnameForbidden; + @Value("${password.max.age}") private int passwordMaxAge; @Value("${password.max.age.author}") @@ -161,6 +210,7 @@ public class LoginModule extends AbstractSpringModule { failedLoginCache = coordinatorManager.getCoordinator().getCacher().getCache(LoginModule.class.getSimpleName(), "blockafterfailedattempts"); updateProperties(); + validateProperties(); boolean defaultProviderFound = false; for (Iterator<AuthenticationProvider> iterator = authenticationProviders.iterator(); iterator.hasNext();) { @@ -177,6 +227,32 @@ public class LoginModule extends AbstractSpringModule { } } + private void validateProperties() { + validateValidationConfig("password.letters", passwordLetters, + Arrays.asList(DISABLED, FORBIDDEN, AT_LEAST_1, AT_LEAST_2, AT_LEAST_3, VALIDATE_SEPARATELY)); + validateValidationConfig("password.letters.uppercase", passwordLettersUppercase, + Arrays.asList(DISABLED, FORBIDDEN, AT_LEAST_1, AT_LEAST_2, AT_LEAST_3)); + validateValidationConfig("password.letters.lowercase", passwordLettersLowercase, + Arrays.asList(DISABLED, FORBIDDEN, AT_LEAST_1, AT_LEAST_2, AT_LEAST_3)); + validateValidationConfig("password.digits.special.signs", passwordDigitsAndSpecialSigns, + Arrays.asList(DISABLED, FORBIDDEN, AT_LEAST_1, AT_LEAST_2, AT_LEAST_3, VALIDATE_SEPARATELY)); + validateValidationConfig("password.digits", passwordDigits, + Arrays.asList(DISABLED, FORBIDDEN, AT_LEAST_1, AT_LEAST_2, AT_LEAST_3)); + validateValidationConfig("password.special.signs", passwordSpecialSigns, + Arrays.asList(DISABLED, FORBIDDEN, AT_LEAST_1, AT_LEAST_2, AT_LEAST_3)); + } + + private void validateValidationConfig(String configName, String configValue, List<String> validValues) { + if (!validValues.contains(configValue)) { + logInvalidValidationConfig(configName, configValue, validValues); + } + } + + private void logInvalidValidationConfig(String configName, String configValue, List<String> validValues) { + log.error("Invalid configuration for " + configName + " (value = " + configValue + "). Valid values are: " + + validValues.stream().collect(Collectors.joining(", "))); + } + @Override protected void initFromChangedProperties() { updateProperties(); @@ -242,11 +318,71 @@ public class LoginModule extends AbstractSpringModule { allowLoginUsingEmail = "true".equals(usernameOrEmailLogin); } + String usernameRegexObj = getStringPropertyValue(USERNAME_REGEX, true); + if(StringHelper.containsNonWhitespace(usernameRegexObj)) { + usernameRegex = usernameRegexObj; + } + String changeOnce = getStringPropertyValue(CHANGE_ONCE, true); if(StringHelper.containsNonWhitespace(changeOnce)) { passwordChangeOnce = "true".equals(changeOnce); } + String passwordMinLengthObj = getStringPropertyValue(MIN_LENGTH, true); + if(StringHelper.containsNonWhitespace(passwordMinLengthObj)) { + passwordMinLength = Integer.parseInt(passwordMinLengthObj); + } + + String passwordMaxLengthObj = getStringPropertyValue(MAX_LENGTH, true); + if(StringHelper.containsNonWhitespace(passwordMaxLengthObj)) { + passwordMaxLength = Integer.parseInt(passwordMaxLengthObj); + } + + String passwordLettersObj = getStringPropertyValue(LETTERS, true); + if(StringHelper.containsNonWhitespace(passwordLettersObj)) { + passwordLetters = passwordLettersObj; + } + + String passwordLettersUppercaseObj = getStringPropertyValue(LETTERS_UPPER, true); + if(StringHelper.containsNonWhitespace(passwordLettersUppercaseObj)) { + passwordLettersUppercase = passwordLettersUppercaseObj; + } + + String passwordLettersLowercaseObj = getStringPropertyValue(LETTERS_LOWER, true); + if(StringHelper.containsNonWhitespace(passwordLettersLowercaseObj)) { + passwordLettersLowercase = passwordLettersLowercaseObj; + } + + String passwordDigitsAndSpecialSignsObj = getStringPropertyValue(DIGITS_SPECIALS, true); + if(StringHelper.containsNonWhitespace(passwordDigitsAndSpecialSignsObj)) { + passwordDigitsAndSpecialSigns = passwordDigitsAndSpecialSignsObj; + } + + String passwordDigitsObj = getStringPropertyValue(DIGITS, true); + if(StringHelper.containsNonWhitespace(passwordDigitsObj)) { + passwordDigits = passwordDigitsObj; + } + + String passwordSpecialSignsObj = getStringPropertyValue(SPECIALS, true); + if(StringHelper.containsNonWhitespace(passwordSpecialSignsObj)) { + passwordSpecialSigns = passwordSpecialSignsObj; + } + + String passwordUsernameForbiddenObj = getStringPropertyValue(FORBIDDEN_USERNAME, true); + if(StringHelper.containsNonWhitespace(passwordUsernameForbiddenObj)) { + passwordUsernameForbidden = "true".equals(passwordUsernameForbiddenObj); + } + + String passwordFirstnameForbiddenObj = getStringPropertyValue(FORBIDDEN_FIRSTNAME, true); + if(StringHelper.containsNonWhitespace(passwordFirstnameForbiddenObj)) { + passwordFirstnameForbidden = "true".equals(passwordFirstnameForbiddenObj); + } + + String passwordLastnameForbiddenObj = getStringPropertyValue(FORBIDDEN_LASTNAME, true); + if(StringHelper.containsNonWhitespace(passwordLastnameForbiddenObj)) { + passwordLastnameForbidden = "true".equals(passwordLastnameForbiddenObj); + } + int validUntilHoursGuiInt = getIntPropertyValue("password.change.valid.hours.gui"); if (validUntilHoursGuiInt > 0) { validUntilHoursGui = validUntilHoursGuiInt; @@ -447,6 +583,23 @@ public class LoginModule extends AbstractSpringModule { setStringProperty("login.using.username.or.email.enabled", Boolean.toString(allow), true); } + public String getUsernameRegex() { + return usernameRegex; + } + + public void setUsernameRegex(String usernameRegex) { + this.usernameRegex = usernameRegex; + this.usernamePattern = null; + setStringProperty(USERNAME_REGEX, usernameRegex, true); + } + + public Pattern getUsernamePattern() { + if (usernamePattern == null) { + usernamePattern = Pattern.compile(usernameRegex); + } + return usernamePattern; + } + public Integer getValidUntilHoursGui() { return validUntilHoursGui; } @@ -474,6 +627,105 @@ public class LoginModule extends AbstractSpringModule { setStringProperty(CHANGE_ONCE, passwordChangeOnce ? "true" : "false", true); } + public int getPasswordMinLength() { + return passwordMinLength; + } + + public void setPasswordMinLength(int passwordMinLength) { + this.passwordMinLength = passwordMinLength; + setStringProperty(MIN_LENGTH, String.valueOf(passwordMinLength), true); + } + + public int getPasswordMaxLength() { + return passwordMaxLength; + } + + public void setPasswordMaxLength(int passwordMaxLength) { + this.passwordMaxLength = passwordMaxLength; + setStringProperty(MAX_LENGTH, String.valueOf(passwordMaxLength), true); + } + + public String getPasswordLetters() { + return passwordLetters; + } + + public void setPasswordLetters(String passwordLetters) { + this.passwordLetters = passwordLetters; + setStringProperty(LETTERS, String.valueOf(passwordLetters), true); + } + + public String getPasswordLettersUppercase() { + return passwordLettersUppercase; + } + + public void setPasswordLettersUppercase(String passwordLettersUppercase) { + this.passwordLettersUppercase = passwordLettersUppercase; + setStringProperty(LETTERS_UPPER, String.valueOf(passwordLettersUppercase), true); + } + + public String getPasswordLettersLowercase() { + return passwordLettersLowercase; + } + + public void setPasswordLettersLowercase(String passwordLettersLowercase) { + this.passwordLettersLowercase = passwordLettersLowercase; + setStringProperty(LETTERS_LOWER, String.valueOf(passwordLettersLowercase), true); + } + + public String getPasswordDigitsAndSpecialSigns() { + return passwordDigitsAndSpecialSigns; + } + + public void setPasswordDigitsAndSpecialSigns(String passwordDigitsAndSpecialSigns) { + this.passwordDigitsAndSpecialSigns = passwordDigitsAndSpecialSigns; + setStringProperty(DIGITS_SPECIALS, String.valueOf(passwordDigitsAndSpecialSigns), true); + } + + public String getPasswordDigits() { + return passwordDigits; + } + + public void setPasswordDigits(String passwordDigits) { + this.passwordDigits = passwordDigits; + setStringProperty(DIGITS, String.valueOf(passwordDigits), true); + } + + public String getPasswordSpecialSigns() { + return passwordSpecialSigns; + } + + public void setPasswordSpecialSigns(String passwordSpecialSigns) { + this.passwordSpecialSigns = passwordSpecialSigns; + setStringProperty(SPECIALS, String.valueOf(passwordSpecialSigns), true); + } + + public boolean isPasswordUsernameForbidden() { + return passwordUsernameForbidden; + } + + public void setPasswordUsernameForbidden(boolean passwordUsernameForbidden) { + this.passwordUsernameForbidden = passwordUsernameForbidden; + setStringProperty(FORBIDDEN_USERNAME, Boolean.toString(passwordUsernameForbidden), true); + } + + public boolean isPasswordFirstnameForbidden() { + return passwordFirstnameForbidden; + } + + public void setPasswordFirstnameForbidden(boolean passwordFirstnameForbidden) { + this.passwordFirstnameForbidden = passwordFirstnameForbidden; + setStringProperty(FORBIDDEN_FIRSTNAME, Boolean.toString(passwordFirstnameForbidden), true); + } + + public boolean isPasswordLastnameForbidden() { + return passwordLastnameForbidden; + } + + public void setPasswordLastnameForbidden(boolean passwordLastnameForbidden) { + this.passwordLastnameForbidden = passwordLastnameForbidden; + setStringProperty(FORBIDDEN_LASTNAME, Boolean.toString(passwordLastnameForbidden), true); + } + public boolean isPasswordAgePolicyConfigured() { return passwordMaxAge > 0 || passwordMaxAgeAuthor > 0 || passwordMaxAgeGroupManager > 0 || passwordMaxAgePoolManager > 0 diff --git a/src/main/java/org/olat/login/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/login/_i18n/LocalStrings_de.properties index abfc5eeda10..db625558b2f 100644 --- a/src/main/java/org/olat/login/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/login/_i18n/LocalStrings_de.properties @@ -40,17 +40,42 @@ accesskey.top=$org.olat.core.commons.fullWebApp\:accesskey.top accesskey.topnav=$org.olat.core.commons.fullWebApp\:accesskey.topnav admin.menu.title=Gast und Einladung admin.menu.title.alt=$\:admin.menu.title - disable.history=ausgeschaltet -password.after=f\uFFFDr {0} \uFFFDnderungen -password.history=Verwendung von vorherigen Passw\uFFFDrtern verhindern -admin.password.menu.title=Passwort-Richtlinien -admin.password.menu.title.alt=Richtlinien \uFFFDber die \uFFFDnderung von Passw\uFFFDrtern +password.after=f\u00FCr {0} \u00C4nderungen +password.history=Verwendung von vorherigen Passw\u00F6rtern verhindern +admin.password.menu.title=Passw\u00F6rter +admin.password.menu.title.alt=Passw\u00F6rter +admin.password.syntax=Syntax-Regeln +admin.password.policy=\u00C4nderungsrichtlinien +admin.syntax.digits.or.specials=Ziffern und Sonderzeichen separat definieren +admin.syntax.digits.specials=Ziffern und Sonderzeichen +admin.syntax.digits=Ziffern +admin.syntax.forbidden.firstname=Vorname des Benutzers +admin.syntax.forbidden.lastname=Nachname des Benutzers +admin.syntax.forbidden.username=Benutzername +admin.syntax.forbidden.values=Nicht erlaubte Werte +admin.syntax.forbidden=Nicht erlaubt +admin.syntax.letters.lower.upper=Gross- und Kleinbuchstaben separat definieren +admin.syntax.letters.lowercase=Kleinbuchstaben +admin.syntax.letters.uppercase=Grossbuchstaben +admin.syntax.letters=Buchstaben +admin.syntax.max.length=Maximall\u00E4nge +admin.syntax.min.1=Mindestends 1 +admin.syntax.min.2=Mindestends 2 +admin.syntax.min.3=Mindestends 3 +admin.syntax.min.length=Minimall\u00E4nge +admin.syntax.permitted=Erlaubt +admin.syntax.preview.description=Validieren Sie ein Passwort gegen\u00FCber den eingestellten Syntax-Regeln. Folgende Regeln sind aktiv:{0} +admin.syntax.preview.password=Passwort +admin.syntax.preview.validate=Validieren +admin.syntax.preview.title=Passwort Syntax Validierung +admin.syntax.preview=Vorschau +admin.syntax.specials=Sonderzeichen change.once=Passwort \u00E4ndern beim ersten Login max.age=Neues Passwort erzwingen nach max.age.hint=in Tagen -max.age.description=Sie k\uFFFDnnen hier festlegen wie oft ein Benutzer sein Passwort \uFFFDndern muss und ob ein Passwort wiederverwendet werden kann. Die Lebensdauer des Passwortes kann pro Rolle festgelegt werden. -max.age.author=... f\uFFFDr Autoren +max.age.description=Sie k\u00F6nnen hier festlegen wie oft ein Benutzer sein Passwort \u00E4ndern muss und ob ein Passwort wiederverwendet werden kann. Die Lebensdauer des Passwortes kann pro Rolle festgelegt werden. +max.age.author=... f\u00FCr Autoren max.age.groupmanager=... Gruppenverwalter max.age.poolmanager=... Fragenpoolverwalter max.age.usermanager=... Benutzerverwalter @@ -63,11 +88,36 @@ max.age.lecturemanager=... Lektionenverwalter max.age.principal=... Principal max.age.administrator=... Administrator max.age.sysadmin=... Systemadministrator -password.policy.title=Passwort-Richtlinien password.change.valid.until.gui=G\u00FCltigkeitsdauer Passwort\u00E4nderung in Stunden (GUI) password.change.valid.until.rest=G\u00FCltigkeitsdauer Passwort\u00E4nderung in Stunden (REST) +password.rule.at.least.digits=Das Password muss mindestens {0} Ziffern beinhalten. +password.rule.at.least.digits.specials=Das Password muss mindestens {0} Ziffern oder Sonderzeichen beinhalten. +password.rule.at.least.letters=Das Password muss mindestens {0} Buchstaben beinhalten. +password.rule.at.least.letters.lowercase=Das Password muss mindestens {0} Kleinbuchstaben beinhalten. +password.rule.at.least.letters.uppercase=Das Password muss mindestens {0} Grossbuchstaben beinhalten. +password.rule.at.least.specials=Das Password muss mindestens {0} Sonderzeichen beinhalten. +password.rule.forbidden.digits=Das Passwort darf keine Ziffern beinhalten. +password.rule.forbidden.digits.specials=Das Passwort darf keine Ziffern und keine Sonderzeichen beinhalten. +password.rule.forbidden.letters=Das Passwort darf keine Buchstaben beinhalten. +password.rule.forbidden.letters.lowercase=Das Passwort darf keine Kleinbuchstaben beinhalten. +password.rule.forbidden.letters.uppercase=Das Passwort darf keine Grossbuchstaben beinhalten. +password.rule.forbidden.specials=Das Passwort darf keine Sonderzeichen beinhalten. +password.rule.forbidden.username=Das Passwort darf nicht den Benutzernamen beinhalten. +password.rule.forbidden.user.firstname=Das Passwort darf nicht den Vornamen beinhalten. +password.rule.forbidden.user.lastname=Das Passwort darf nicht den Nachnamen beinhalten. +password.rule.history=Sie d\u00FCrfen nicht ein Passwort, das Sie schon hatten, wieder verwenden. +password.rule.length=Das Password muss insgesamt zwischen {0} und {1} Zeichen lang sein. +password.rule.permitted.digits.specials=Ziffern und Sonderzeichen sind zul\u00E4ssig. +password.rule.permitted.digits=Ziffern sind zul\u00E4ssig. +password.rule.permitted.letters.lowercase=Kleinbuchstaben sind zul\u00E4ssig. +password.rule.permitted.letters.uppercase=Grossbuchstaben sind zul\u00E4ssig. +password.rule.permitted.letters=Buchstaben sind zul\u00E4ssig. +password.rule.permitted.specials=Sonderzeichen sind zul\u00E4ssig. +username.rule.syntax=$org.olat.user\:form.checkUsername +username.rule.blacklist=$org.olat.registration\:form.check6 +username.rule.in.use=$org.olat.registration\:form.check6 +error.password.length.lower=Die Maximall\u00E4nge muss gr\u00F6sser sein als die Minimall\u00E4nge. error.wrong.int=Falsches Zahlenformat. - authentication.provider.description=Geh\u00F6ren Sie keiner der oben aufgelisteten Institutionen an oder haben ein lokales Nutzerkonto? authentication.provider.linkText=Anmelden mit OpenOLAT Konto browsercheck.bestresults.newerversion=oder neuere Version diff --git a/src/main/java/org/olat/login/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/login/_i18n/LocalStrings_en.properties index 11464d9aabd..b8834d6f307 100644 --- a/src/main/java/org/olat/login/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/login/_i18n/LocalStrings_en.properties @@ -40,12 +40,37 @@ accesskey.top=$org.olat.core.commons.fullWebApp\:accesskey.top accesskey.topnav=$org.olat.core.commons.fullWebApp\:accesskey.topnav admin.menu.title=Guest and invitation admin.menu.title.alt=$\:admin.menu.title - disable.history=disabled password.after=for {0} changes password.history=Prevent reuse of previous passwords -admin.password.menu.title=Password policy -admin.password.menu.title.alt=Policy about changing of passwords +admin.password.menu.title.alt=Passwords +admin.password.menu.title=Passwords +admin.password.policy=Change policies +admin.password.syntax=Syntax rules +admin.syntax.digits.or.specials=Separat definition of digits and special signs +admin.syntax.digits.specials=Digits and special signs +admin.syntax.digits=Digits +admin.syntax.forbidden.firstname=Firstname of user +admin.syntax.forbidden.lastname=Lastname of user +admin.syntax.forbidden.username=Username +admin.syntax.forbidden.values=Forbidden values +admin.syntax.forbidden=Forbidden +admin.syntax.letters.lower.upper=Separat definition of uppercase and lowercase letters +admin.syntax.letters.lowercase=Lowercase letters +admin.syntax.letters.uppercase=Uppercase letters +admin.syntax.letters=Letters +admin.syntax.max.length=Maximum length +admin.syntax.min.1=At least 1 +admin.syntax.min.2=At least 2 +admin.syntax.min.3=At least 3 +admin.syntax.min.length=Minimum length +admin.syntax.permitted=Permitted +admin.syntax.preview.description=Validate a password against the selected rules. The rules are:{0} +admin.syntax.preview.password=Password +admin.syntax.preview.validate=Validate +admin.syntax.preview.title=Validation of psswort syntax +admin.syntax.preview=Preview +admin.syntax.specials=Special signs change.once=Change password on first login max.age=Enforce new password after max.age.hint=in days @@ -63,9 +88,35 @@ max.age.learnresourcemanager=... for learning resource manager max.age.principal=... for principal max.age.administrator=... for administrator max.age.sysadmin=... for system administrator -password.policy.title=Password policies password.change.valid.until.gui=Password change validity period in hours (GUI) password.change.valid.until.rest=Password change validity period in hours (REST) +password.rule.at.least.digits.specials=The password has to contain at least {0} digits or special signs. +password.rule.at.least.digits=The password has to contain at least {0} digits. +password.rule.at.least.letters.lowercase=The password has to contain at least {0} lowercase letters. +password.rule.at.least.letters.uppercase=The password has to contain at least {0} uppercase letters. +password.rule.at.least.letters=The password has to contain at least {0} letters. +password.rule.at.least.specials=The password has to contain at least {0} special signs. +password.rule.forbidden.digits.specials=The password must not contain any digits or special characters. +password.rule.forbidden.digits=The password must not contain any digits. +password.rule.forbidden.letters.lowercase=The password must not contain any lowercase letters. +password.rule.forbidden.letters.uppercase=The password must not contain any uppercase letters. +password.rule.forbidden.letters=The password must not contain any letters. +password.rule.forbidden.specials=The password must not contain any special signs. +password.rule.forbidden.user.firstname=The password must not contain the first name. +password.rule.forbidden.user.lastname=The password must not contain the last name. +password.rule.forbidden.username=The password must not contain the username. +password.rule.history=You cannot use a password you already used in the past +password.rule.length=The password has to contain at least {0} and at most {1} characters. +password.rule.permitted.digits.specials=Digits and special signs are permitted. +password.rule.permitted.digits=Digits signs are permitted. +password.rule.permitted.letters.lowercase=Lowercase letters are permitted. +password.rule.permitted.letters.uppercase=Uppercase letters are permitted. +password.rule.permitted.letters=Letters and special signs are permitted. +password.rule.permitted.specials=Special signs are permitted. +username.rule.syntax=$org.olat.user\:form.checkUsername +username.rule.blacklist=$org.olat.registration\:form.check6 +username.rule.in.use=$org.olat.registration\:form.check6 +error.password.length.lower=The maximal length has to be higher than the minimum length. error.wrong.int=Wrong numerical format authentication.provider.description=Don't you belong to one of the institutions mentioned above or have a local user account? diff --git a/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties index 79e681facde..780a13bac02 100644 --- a/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/login/_i18n/LocalStrings_fr.properties @@ -40,8 +40,8 @@ accesskey.top=$org.olat.core.commons.fullWebApp\:accesskey.top accesskey.topnav=$org.olat.core.commons.fullWebApp\:accesskey.topnav admin.menu.title=Invit\u00E9s et invitations admin.menu.title.alt=$\:admin.menu.title -admin.password.menu.title=R\u00E8gles concernant les mots de passes -admin.password.menu.title.alt=R\u00E8gles concernant les changements de mots de passes +admin.password.menu.title=Mots de passes +admin.password.menu.title.alt=Mots de passes authentication.provider.description=N'appertenez-vous pas \u00E0 l'une des institutions mentionn\u00E9es ci-dessus ou n'avez-vous pas un compte utilisateur local? authentication.provider.linkText=Connectez-vous avec un compte OpenOLAT browsercheck.bestresults.newerversion=ou nouvelle version @@ -135,7 +135,7 @@ password.after=pour {0} changements password.change.valid.until.gui=Dur\u00E9e de validit\u00E9 des mots de passes (UI) password.change.valid.until.rest=Dur\u00E9e de validit\u00E9 des mots de passes (REST) password.history=Pr\u00E9venir la r\u00E9utilisation des mots de passes pr\u00E9c\u00E9dants -password.policy.title=R\u00E8gles concernant les mots de passes +password.rule.history=Vous ne pouvez pas r\u00E9utiliser un mot de passe que vous avez d\u00E9j\u00E0 utilis\u00E9 par le pass\u00E9. runonce.forced=Veuillez compl\u00E9ter toutes les indications et enregistrez le formulaire, s.v.p. . runonce.title=Modifications r\u00E9currentes / r\u00E9glages \u00E0 la premi\u00E8re connexion shib.redirect=Shibboleth Login diff --git a/src/main/java/org/olat/login/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/login/_i18n/LocalStrings_pt_BR.properties index 40a7f7e3b0a..b23bc69730c 100644 --- a/src/main/java/org/olat/login/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/login/_i18n/LocalStrings_pt_BR.properties @@ -38,8 +38,8 @@ accesskey.top=$org.olat.core.commons.fullWebApp\:accesskey.top accesskey.topnav=$org.olat.core.commons.fullWebApp\:accesskey.topnav admin.menu.title=Convidados e convites admin.menu.title.alt=$\:admin.menu.title -admin.password.menu.title=Pol\u00EDtica de senha -admin.password.menu.title.alt=Pol\u00EDtica sobre altera\u00E7\u00F5es de senhas +admin.password.menu.title=Senha +admin.password.menu.title.alt=Senhas authentication.provider.description=Voc\u00EA n\u00E3o pertence a uma das institui\u00E7\u00F5es mencionadas acima ou possui uma conta de usu\u00E1rio local? authentication.provider.linkText=Entrar com conta OpenOLAT browsercheck.bestresults.newerversion=ou vers\u00E3o mais atual @@ -131,7 +131,7 @@ password.after=para {0} mudan\u00E7as password.change.valid.until.gui=Per\u00EDodo de validade da mudan\u00E7a de senha em horas (GUI) password.change.valid.until.rest=Per\u00EDodo de validade da mudan\u00E7a de senha em horas (REST) password.history=Previnir reaproveitamento de senhas anteriores -password.policy.title=Pol\u00EDticas de senhas +password.rule.history=Voc\u00EA n\u00E3o pode usar uma senha que j\u00E1 usou no passado runonce.forced=Por favor, preencha este formul\u00E1rio e salve as configura\u00E7\u00F5es. runonce.title=Modifica\u00E7\u00F5es/Ajustes recorrentes ao entrar pela primeira vez shib.redirect=Shibboleth Login diff --git a/src/main/java/org/olat/login/_spring/loginContext.xml b/src/main/java/org/olat/login/_spring/loginContext.xml index 1db16d14b09..3b6172d019d 100644 --- a/src/main/java/org/olat/login/_spring/loginContext.xml +++ b/src/main/java/org/olat/login/_spring/loginContext.xml @@ -74,10 +74,10 @@ <property name="order" value="8810" /> <property name="actionController"> <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> - <property name="className" value="org.olat.login.ui.PasswordPolicyController"/> + <property name="className" value="org.olat.login.ui.PasswordAdminController"/> </bean> </property> - <property name="navigationKey" value="passwordpolicy" /> + <property name="navigationKey" value="passwords" /> <property name="i18nActionKey" value="admin.password.menu.title"/> <property name="i18nDescriptionKey" value="admin.password.menu.title.alt"/> <property name="translationPackage" value="org.olat.login"/> diff --git a/src/main/java/org/olat/login/auth/OLATAuthManager.java b/src/main/java/org/olat/login/auth/OLATAuthManager.java index c74b27f0779..1b019807cb2 100644 --- a/src/main/java/org/olat/login/auth/OLATAuthManager.java +++ b/src/main/java/org/olat/login/auth/OLATAuthManager.java @@ -30,9 +30,9 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import org.apache.logging.log4j.Logger; import org.olat.basesecurity.Authentication; import org.olat.basesecurity.BaseSecurity; -import org.olat.basesecurity.BaseSecurityModule; import org.olat.basesecurity.IdentityRef; import org.olat.basesecurity.manager.AuthenticationDAO; import org.olat.core.commons.services.webdav.manager.WebDAVAuthManager; @@ -41,7 +41,6 @@ import org.olat.core.id.Identity; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.logging.AssertException; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.Encoder.Algorithm; import org.olat.core.util.StringHelper; @@ -63,6 +62,9 @@ import org.olat.login.LoginModule; import org.olat.login.OLATAuthenticationController; import org.olat.login.oauth.OAuthLoginModule; import org.olat.login.oauth.OAuthSPI; +import org.olat.login.validation.PasswordValidationRulesFactory; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.UsernameValidationRulesFactory; import org.olat.registration.RegistrationManager; import org.olat.registration.TemporaryKey; import org.olat.shibboleth.ShibbolethDispatcher; @@ -99,6 +101,10 @@ public class OLATAuthManager implements AuthenticationSPI { private AuthenticationDAO authenticationDao; @Autowired private RegistrationManager registrationManager; + @Autowired + private PasswordValidationRulesFactory passwordRulesFactory; + @Autowired + private UsernameValidationRulesFactory usernameRulesFactory; /** * @@ -195,7 +201,16 @@ public class OLATAuthManager implements AuthenticationSPI { } } } - return null; + return null; + } + + public SyntaxValidator createUsernameSytaxValidator() { + return new SyntaxValidator(usernameRulesFactory.createRules(), false); + } + + + public SyntaxValidator createPasswordSytaxValidator() { + return new SyntaxValidator(passwordRulesFactory.createRules(), true); } /** @@ -344,24 +359,4 @@ public class OLATAuthManager implements AuthenticationSPI { return changePassword(identity, identity, newPwd); } - - /** - * Check the credential history if configured and if the user - * has not a LDAP credential. - * - * @param identity The identity - * @param password The new password - * @return true if the new password is valid against the history - */ - public boolean checkCredentialHistory(Identity identity, String password) { - boolean ok = true; - int historyLength = loginModule.getPasswordHistory(); - if(historyLength > 0 && - (!ldapLoginModule.isLDAPEnabled() - || !authenticationDao.hasAuthentication(identity, LDAPAuthenticationController.PROVIDER_LDAP))) { - ok = securityManager.checkCredentialHistory(identity, BaseSecurityModule.getDefaultAuthProviderIdentifier(), password); - } - return ok; - } - } diff --git a/src/main/java/org/olat/login/auth/OLATAuthentcationForm.java b/src/main/java/org/olat/login/auth/OLATAuthentcationForm.java index 66fecc136f3..73f7d3742a3 100644 --- a/src/main/java/org/olat/login/auth/OLATAuthentcationForm.java +++ b/src/main/java/org/olat/login/auth/OLATAuthentcationForm.java @@ -58,7 +58,7 @@ public class OLATAuthentcationForm extends FormBasicController { /** - * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest) + * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest, Identity) */ @Override public boolean validateFormLogic(UserRequest ureq) { diff --git a/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java b/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java index 7ec37f240c8..19e96851e51 100644 --- a/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java +++ b/src/main/java/org/olat/login/oauth/ui/OAuthRegistrationController.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import org.olat.admin.user.delete.service.UserDeletionManager; +import org.olat.admin.user.imp.TransientIdentity; import org.olat.basesecurity.AuthHelper; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.OrganisationRoles; @@ -46,13 +47,16 @@ import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; +import org.olat.login.auth.OLATAuthManager; import org.olat.login.oauth.model.OAuthRegistration; import org.olat.login.oauth.model.OAuthUser; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.registration.DisclaimerController; import org.olat.registration.RegistrationForm2; import org.olat.registration.RegistrationManager; +import org.olat.user.ChangePasswordForm; import org.olat.user.UserManager; -import org.olat.user.UserModule; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; @@ -68,6 +72,7 @@ public class OAuthRegistrationController extends FormBasicController { private final OAuthRegistration registration; private final List<UserPropertyHandler> userPropertyHandlers; + private final SyntaxValidator usernameSyntaxValidator; private TextElement usernameEl; private SingleSelection langEl; @@ -77,13 +82,13 @@ public class OAuthRegistrationController extends FormBasicController { private Identity authenticatedIdentity; - @Autowired - private UserModule userModule; @Autowired private UserManager userManager; @Autowired private BaseSecurity securityManager; @Autowired + private OLATAuthManager olatAuthManager; + @Autowired private UserDeletionManager userDeletionManager; @Autowired private OrganisationService organisationService; @@ -94,7 +99,9 @@ public class OAuthRegistrationController extends FormBasicController { super(ureq, wControl); setTranslator(Util.createPackageTranslator(RegistrationForm2.class, getLocale(), getTranslator())); setTranslator(Util.createPackageTranslator(UserPropertyHandler.class, getLocale(), getTranslator())); + setTranslator(Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale(), getTranslator())); userPropertyHandlers = userManager.getUserPropertyHandlersFor(USERPROPERTIES_FORM_IDENTIFIER, false); + this.usernameSyntaxValidator = olatAuthManager.createUsernameSytaxValidator(); this.registration = registration; @@ -180,18 +187,23 @@ public class OAuthRegistrationController extends FormBasicController { } } - String login = usernameEl.getValue(); + String username = usernameEl.getValue(); + TransientIdentity newIdentity = new TransientIdentity(); + newIdentity.setName(username); + for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { + FormItem propertyItem = flc.getFormComponent(userPropertyHandler.getName()); + newIdentity.setProperty(userPropertyHandler.getName(), userPropertyHandler.getStringValue(propertyItem)); + } + usernameEl.clearError(); - if (!userManager.syntaxCheckOlatLogin(login)) { - usernameEl.setErrorKey("form.check3", null); - allOk &= false; - } else if (userModule.isLoginOnBlacklist(login)) { - usernameEl.setErrorKey("form.check6", null); + if (!StringHelper.containsNonWhitespace(username)) { + usernameEl.setErrorKey("form.legende.mandatory", null); allOk &= false; } else { - Identity s = securityManager.findIdentityByName(login); - if (s != null) { - usernameEl.setErrorKey("form.check6", null); + ValidationResult validationResult = usernameSyntaxValidator.validate(username, newIdentity); + if (!validationResult.isValid()) { + String descriptions = validationResult.getInvalidDescriptions().get(0).getText(getLocale()); + usernameEl.setErrorKey("error.username.invalid", new String[] { descriptions }); allOk &= false; } } diff --git a/src/main/java/org/olat/login/ui/LoginUIFactory.java b/src/main/java/org/olat/login/ui/LoginUIFactory.java new file mode 100644 index 00000000000..15c57a41844 --- /dev/null +++ b/src/main/java/org/olat/login/ui/LoginUIFactory.java @@ -0,0 +1,65 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.ui; + +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.util.StringHelper; +import org.olat.login.validation.ValidationDescription; + +/** + * + * Initial date: 14 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class LoginUIFactory { + + public static String formatDescriptionAsList(List<ValidationDescription> descriptions, Locale locale) { + return descriptions.stream() + .map(d -> "<br/> - " + d.getText(locale)) + .collect(Collectors.joining()); + } + + static boolean validateInteger(TextElement el, int min) { + boolean allOk = true; + el.clearError(); + String val = el.getValue(); + if(StringHelper.containsNonWhitespace(val)) { + try { + double value = Integer.parseInt(val); + if(min > value) { + el.setErrorKey("error.wrong.int", null); + allOk = false; + } + } catch (NumberFormatException e) { + el.setErrorKey("error.wrong.int", null); + allOk = false; + } + } else { + el.setErrorKey("error.wrong.int", null); + allOk = false; + } + return allOk; + } +} diff --git a/src/main/java/org/olat/login/ui/PasswordAdminController.java b/src/main/java/org/olat/login/ui/PasswordAdminController.java new file mode 100644 index 00000000000..88427b5d880 --- /dev/null +++ b/src/main/java/org/olat/login/ui/PasswordAdminController.java @@ -0,0 +1,133 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.ui; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.segmentedview.SegmentViewComponent; +import org.olat.core.gui.components.segmentedview.SegmentViewEvent; +import org.olat.core.gui.components.segmentedview.SegmentViewFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; +import org.olat.core.util.Util; +import org.olat.core.util.resource.OresHelper; +import org.olat.login.LoginModule; + +/** + * + * Initial date: 14 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class PasswordAdminController extends BasicController implements Activateable2 { + + private static final String SYNTAX_RES_TYPE = "syntax"; + private static final String POLICY_RES_TYPE = "policy"; + + private VelocityContainer mainVC; + private final Link syntaxLink; + private final Link policyLink; + private final SegmentViewComponent segmentView; + + private PasswordSyntaxController syntaxCtrl; + private PasswordPolicyController policyCtrl; + + public PasswordAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + setTranslator(Util.createPackageTranslator(LoginModule.class, ureq.getLocale(), getTranslator())); + + mainVC = createVelocityContainer("admin"); + + segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); + syntaxLink = LinkFactory.createLink("admin.password.syntax", mainVC, this); + segmentView.addSegment(syntaxLink, true); + policyLink = LinkFactory.createLink("admin.password.policy", mainVC, this); + segmentView.addSegment(policyLink, false); + + doOpenSyntax(ureq); + putInitialPanel(mainVC); + } + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + if(entries == null || entries.isEmpty()) return; + + String type = entries.get(0).getOLATResourceable().getResourceableTypeName(); + if(SYNTAX_RES_TYPE.equalsIgnoreCase(type)) { + doOpenSyntax(ureq); + segmentView.select(syntaxLink); + } else if(POLICY_RES_TYPE.equalsIgnoreCase(type)) { + doOpenPolicy(ureq); + segmentView.select(policyLink); + } + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(source == segmentView) { + if(event instanceof SegmentViewEvent) { + SegmentViewEvent sve = (SegmentViewEvent)event; + String segmentCName = sve.getComponentName(); + Component clickedLink = mainVC.getComponent(segmentCName); + if (clickedLink == syntaxLink) { + doOpenSyntax(ureq); + } else if (clickedLink == policyLink) { + doOpenPolicy(ureq); + } + } + } + } + + private void doOpenSyntax(UserRequest ureq) { + if(syntaxCtrl == null) { + WindowControl swControl = addToHistory(ureq, OresHelper.createOLATResourceableType(SYNTAX_RES_TYPE), null); + syntaxCtrl = new PasswordSyntaxController(ureq, swControl); + listenTo(syntaxCtrl); + } else { + addToHistory(ureq, syntaxCtrl); + } + mainVC.put("segmentCmp", syntaxCtrl.getInitialComponent()); + } + + private void doOpenPolicy(UserRequest ureq) { + if(policyCtrl == null) { + WindowControl swControl = addToHistory(ureq, OresHelper.createOLATResourceableType(POLICY_RES_TYPE), null); + policyCtrl = new PasswordPolicyController(ureq, swControl); + listenTo(policyCtrl); + } else { + addToHistory(ureq, policyCtrl); + } + mainVC.put("segmentCmp", policyCtrl.getInitialComponent()); + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/login/ui/PasswordPolicyController.java b/src/main/java/org/olat/login/ui/PasswordPolicyController.java index 04fd0366b6b..5cd66f09ee1 100644 --- a/src/main/java/org/olat/login/ui/PasswordPolicyController.java +++ b/src/main/java/org/olat/login/ui/PasswordPolicyController.java @@ -19,11 +19,12 @@ */ package org.olat.login.ui; +import static org.olat.login.ui.LoginUIFactory.validateInteger; + import org.olat.basesecurity.OrganisationRoles; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; -import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; @@ -44,7 +45,6 @@ public class PasswordPolicyController extends FormBasicController { private static final String[] onKeys = new String[] { "on" }; - private SingleSelection historyEl; private MultipleSelectionElement changeOnceEl; private TextElement validUntilGuiEl; @@ -76,7 +76,6 @@ public class PasswordPolicyController extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - setFormTitle("password.policy.title"); setFormDescription("max.age.description"); validUntilGuiEl = uifactory.addTextElement("password.change.valid.until.gui", 20, loginModule.getValidUntilHoursGui().toString(), formLayout); @@ -89,22 +88,6 @@ public class PasswordPolicyController extends FormBasicController { if(loginModule.isPasswordChangeOnce()) { changeOnceEl.select(onKeys[0], true); } - - String selectedVal = Integer.toString(loginModule.getPasswordHistory()); - boolean hasVal = false; - String[] historyKeys = new String[] { "0", "1", "2", "5", "10", "15" }; - for(String historyKey:historyKeys) { - if(selectedVal.equals(historyKey)) { - hasVal = true; - } - } - String[] historyValues = new String[] { translate("disable.history"), translate("password.after","1"), translate("password.after","2"), translate("password.after","5"), translate("password.after","10"), translate("password.after","15")}; - if(!hasVal) { - historyKeys = append(historyKeys, selectedVal); - historyValues = append(historyValues, selectedVal); - } - historyEl = uifactory.addDropdownSingleselect("password.history", "password.history", formLayout, historyKeys, historyValues, null); - historyEl.select(selectedVal, true); String maxAge = toMaxAgeAsString(loginModule.getPasswordMaxAge()); maxAgeEl = uifactory.addTextElement("max.age", "max.age", 5, maxAge, formLayout); @@ -154,13 +137,6 @@ public class PasswordPolicyController extends FormBasicController { uifactory.addFormSubmitButton("save", buttonsCont); } - private String[] append(String[] array, String val) { - String[] newArray = new String[array.length + 1]; - System.arraycopy(array, 0, newArray, 0, array.length); - newArray[array.length] = val; - return newArray; - } - private String toMaxAgeAsString(int maxAge) { if(maxAge < 0) { return ""; @@ -197,37 +173,9 @@ public class PasswordPolicyController extends FormBasicController { allOk &= validateMaxAgeEl(maxAgeAdministratorEl); allOk &= validateMaxAgeEl(maxAgeSysAdminEl); - historyEl.clearError(); - if(!historyEl.isOneSelected()) { - historyEl.setErrorKey("form.legende.mandatory", null); - allOk &= false; - } - return allOk; } - private boolean validateInteger(TextElement el, int min) { - boolean allOk = true; - el.clearError(); - String val = el.getValue(); - if(StringHelper.containsNonWhitespace(val)) { - try { - double value = Integer.parseInt(val); - if(min > value) { - el.setErrorKey("error.wrong.int", null); - allOk = false; - } - } catch (NumberFormatException e) { - el.setErrorKey("error.wrong.int", null); - allOk = false; - } - } else { - el.setErrorKey("error.wrong.int", null); - allOk = false; - } - return allOk; - } - private boolean validateMaxAgeEl(TextElement el) { boolean allOk = true; @@ -245,9 +193,6 @@ public class PasswordPolicyController extends FormBasicController { protected void formOK(UserRequest ureq) { loginModule.setPasswordChangeOnce(changeOnceEl.isAtLeastSelected(1)); - int history = Integer.parseInt(historyEl.getSelectedKey()); - loginModule.setPasswordHistory(history); - Integer validUntilHoursGui = Integer.parseInt(validUntilGuiEl.getValue()); loginModule.setValidUntilHoursGui(validUntilHoursGui); Integer validUntilHoursRest = Integer.parseInt(validUntilRestEl.getValue()); diff --git a/src/main/java/org/olat/login/ui/PasswordPreviewController.java b/src/main/java/org/olat/login/ui/PasswordPreviewController.java new file mode 100644 index 00000000000..323c14112cc --- /dev/null +++ b/src/main/java/org/olat/login/ui/PasswordPreviewController.java @@ -0,0 +1,106 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.ui; + +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.Util; +import org.olat.login.LoginModule; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; +import org.olat.user.ChangePasswordForm; + +/** + * + * Initial date: 20 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class PasswordPreviewController extends FormBasicController { + + private TextElement passwordEl; + private FormLink closeLink; + + private final SyntaxValidator syntaxValidator; + + protected PasswordPreviewController(UserRequest ureq, WindowControl wControl, SyntaxValidator syntaxValidator) { + super(ureq, wControl); + this.syntaxValidator = syntaxValidator; + setTranslator(Util.createPackageTranslator(LoginModule.class, ureq.getLocale(), getTranslator())); + setTranslator(Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale(), getTranslator())); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String descriptions = formatDescriptionAsList(syntaxValidator.getAllDescriptions(), getLocale()); + setFormDescription("admin.syntax.preview.description", new String[] { descriptions }); + + passwordEl = uifactory.addPasswordElement("admin.syntax.preview.password", "admin.syntax.preview.password", 10000, "", formLayout); + passwordEl.setAutocomplete("new-password"); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("admin.syntax.preview.validate", buttonsCont); + closeLink = uifactory.addFormLink("close", buttonsCont, Link.BUTTON); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == closeLink) { + fireEvent(ureq, FormEvent.DONE_EVENT); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + passwordEl.clearError(); + String newPassword = passwordEl.getValue(); + ValidationResult validationResult = syntaxValidator.validate(newPassword, getIdentity()); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + passwordEl.setErrorKey("error.password.invalid", new String[] { descriptions }); + } + return super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + // Nothing to do. It is only important to validate the password. + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/login/ui/PasswordSyntaxController.java b/src/main/java/org/olat/login/ui/PasswordSyntaxController.java new file mode 100644 index 00000000000..213270614c1 --- /dev/null +++ b/src/main/java/org/olat/login/ui/PasswordSyntaxController.java @@ -0,0 +1,386 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.ui; + +import static org.olat.core.gui.components.util.KeyValues.entry; +import static org.olat.login.LoginModule.AT_LEAST_1; +import static org.olat.login.LoginModule.AT_LEAST_2; +import static org.olat.login.LoginModule.AT_LEAST_3; +import static org.olat.login.LoginModule.DISABLED; +import static org.olat.login.LoginModule.FORBIDDEN; +import static org.olat.login.LoginModule.VALIDATE_SEPARATELY; +import static org.olat.login.ui.LoginUIFactory.validateInteger; + +import java.util.Collection; + +import org.apache.logging.log4j.Logger; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.util.KeyValues; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; +import org.olat.core.logging.Tracing; +import org.olat.core.util.Util; +import org.olat.login.LoginModule; +import org.olat.login.validation.PasswordValidationConfig; +import org.olat.login.validation.PasswordValidationRulesFactory; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationRulesProvider; +import org.olat.login.validation.PasswordValidationConfig.Builder; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 14 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class PasswordSyntaxController extends FormBasicController { + + private static final Logger log = Tracing.createLoggerFor(PasswordSyntaxController.class); + + private static final String FORBIDDEN_USERNAME = "username"; + private static final String FORBIDDEN_FIRSTNAME = "firstname"; + private static final String FORBIDDEN_LASTNAME = "lastname"; + + private TextElement minLengthEl; + private TextElement maxLengthEl; + private SingleSelection lettersEl; + private SingleSelection lettersUppercaseEl; + private SingleSelection lettersLowercaseEl; + private SingleSelection digitsAndSpecialsEl; + private SingleSelection digitsEl; + private SingleSelection specialsEl; + private MultipleSelectionElement forbiddenValuesEl; + private SingleSelection historyEl; + private FormLink previewLink; + + private CloseableModalController cmc; + private PasswordPreviewController previewCtrl; + + @Autowired + private LoginModule loginModule; + @Autowired + private PasswordValidationRulesFactory passwordValidationRulesFactory; + + public PasswordSyntaxController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + setTranslator(Util.createPackageTranslator(LoginModule.class, ureq.getLocale(), getTranslator())); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + minLengthEl = uifactory.addTextElement("admin.syntax.min.length", 10, + String.valueOf(loginModule.getPasswordMinLength()), formLayout); + minLengthEl.setMandatory(true); + + maxLengthEl = uifactory.addTextElement("admin.syntax.max.length", 10, + String.valueOf(loginModule.getPasswordMaxLength()), formLayout); + maxLengthEl.setMandatory(true); + + KeyValues lettersKV = new KeyValues(); + lettersKV.add(entry(DISABLED, translate("admin.syntax.permitted"))); + lettersKV.add(entry(AT_LEAST_1, translate("admin.syntax.min.1"))); + lettersKV.add(entry(AT_LEAST_2, translate("admin.syntax.min.2"))); + lettersKV.add(entry(AT_LEAST_3, translate("admin.syntax.min.3"))); + lettersKV.add(entry(FORBIDDEN, translate("admin.syntax.forbidden"))); + lettersKV.add(entry(VALIDATE_SEPARATELY, translate("admin.syntax.letters.lower.upper"))); + lettersEl = uifactory.addDropdownSingleselect("admin.syntax.letters", formLayout, lettersKV.keys(), + lettersKV.values()); + lettersEl.select(loginModule.getPasswordLetters(), true); + lettersEl.addActionListener(FormEvent.ONCHANGE); + + KeyValues lettersUppercaseKV = new KeyValues(); + lettersUppercaseKV.add(entry(DISABLED, translate("admin.syntax.permitted"))); + lettersUppercaseKV.add(entry(AT_LEAST_1, translate("admin.syntax.min.1"))); + lettersUppercaseKV.add(entry(AT_LEAST_2, translate("admin.syntax.min.2"))); + lettersUppercaseKV.add(entry(AT_LEAST_3, translate("admin.syntax.min.3"))); + lettersUppercaseKV.add(entry(FORBIDDEN, translate("admin.syntax.forbidden"))); + lettersUppercaseEl = uifactory.addDropdownSingleselect("admin.syntax.letters.uppercase", formLayout, + lettersUppercaseKV.keys(), lettersUppercaseKV.values()); + lettersUppercaseEl.select(loginModule.getPasswordLettersUppercase(), true); + + KeyValues lettersLowercaseKV = new KeyValues(); + lettersLowercaseKV.add(entry(DISABLED, translate("admin.syntax.permitted"))); + lettersLowercaseKV.add(entry(AT_LEAST_1, translate("admin.syntax.min.1"))); + lettersLowercaseKV.add(entry(AT_LEAST_2, translate("admin.syntax.min.2"))); + lettersLowercaseKV.add(entry(AT_LEAST_3, translate("admin.syntax.min.3"))); + lettersLowercaseKV.add(entry(FORBIDDEN, translate("admin.syntax.forbidden"))); + lettersLowercaseEl = uifactory.addDropdownSingleselect("admin.syntax.letters.lowercase", formLayout, + lettersLowercaseKV.keys(), lettersLowercaseKV.values()); + lettersLowercaseEl.select(loginModule.getPasswordLettersLowercase(), true); + + KeyValues digitsOrSpecialsKV = new KeyValues(); + digitsOrSpecialsKV.add(entry(DISABLED, translate("admin.syntax.permitted"))); + digitsOrSpecialsKV.add(entry(AT_LEAST_1, translate("admin.syntax.min.1"))); + digitsOrSpecialsKV.add(entry(AT_LEAST_2, translate("admin.syntax.min.2"))); + digitsOrSpecialsKV.add(entry(AT_LEAST_3, translate("admin.syntax.min.3"))); + digitsOrSpecialsKV.add(entry(FORBIDDEN, translate("admin.syntax.forbidden"))); + digitsOrSpecialsKV.add(entry(VALIDATE_SEPARATELY, translate("admin.syntax.digits.or.specials"))); + digitsAndSpecialsEl = uifactory.addDropdownSingleselect("admin.syntax.digits.specials", formLayout, digitsOrSpecialsKV.keys(), + digitsOrSpecialsKV.values()); + digitsAndSpecialsEl.select(loginModule.getPasswordDigitsAndSpecialSigns(), true); + digitsAndSpecialsEl.addActionListener(FormEvent.ONCHANGE); + + KeyValues digitsKV = new KeyValues(); + digitsKV.add(entry(DISABLED, translate("admin.syntax.permitted"))); + digitsKV.add(entry(AT_LEAST_1, translate("admin.syntax.min.1"))); + digitsKV.add(entry(AT_LEAST_2, translate("admin.syntax.min.2"))); + digitsKV.add(entry(AT_LEAST_3, translate("admin.syntax.min.3"))); + digitsKV.add(entry(FORBIDDEN, translate("admin.syntax.forbidden"))); + digitsEl = uifactory.addDropdownSingleselect("admin.syntax.digits", formLayout, digitsKV.keys(), + digitsKV.values()); + digitsEl.select(loginModule.getPasswordDigits(), true); + + KeyValues specialsKV = new KeyValues(); + specialsKV.add(entry(DISABLED, translate("admin.syntax.permitted"))); + specialsKV.add(entry(AT_LEAST_1, translate("admin.syntax.min.1"))); + specialsKV.add(entry(AT_LEAST_2, translate("admin.syntax.min.2"))); + specialsKV.add(entry(AT_LEAST_3, translate("admin.syntax.min.3"))); + specialsKV.add(entry(FORBIDDEN, translate("admin.syntax.forbidden"))); + specialsEl = uifactory.addDropdownSingleselect("admin.syntax.specials", formLayout, specialsKV.keys(), + specialsKV.values()); + specialsEl.select(loginModule.getPasswordSpecialSigns(), true); + + KeyValues forbiddenValuesKV = new KeyValues(); + forbiddenValuesKV.add(entry(FORBIDDEN_USERNAME, translate("admin.syntax.forbidden.username"))); + forbiddenValuesKV.add(entry(FORBIDDEN_FIRSTNAME, translate("admin.syntax.forbidden.firstname"))); + forbiddenValuesKV.add(entry(FORBIDDEN_LASTNAME, translate("admin.syntax.forbidden.lastname"))); + forbiddenValuesEl = uifactory.addCheckboxesVertical("admin.syntax.forbidden.values", formLayout, + forbiddenValuesKV.keys(), forbiddenValuesKV.values(), 1); + forbiddenValuesEl.select(FORBIDDEN_USERNAME, loginModule.isPasswordUsernameForbidden()); + forbiddenValuesEl.select(FORBIDDEN_FIRSTNAME, loginModule.isPasswordFirstnameForbidden()); + forbiddenValuesEl.select(FORBIDDEN_LASTNAME, loginModule.isPasswordLastnameForbidden()); + + String selectedVal = Integer.toString(loginModule.getPasswordHistory()); + boolean hasVal = false; + String[] historyKeys = new String[] { "0", "1", "2", "5", "10", "15" }; + for(String historyKey:historyKeys) { + if(selectedVal.equals(historyKey)) { + hasVal = true; + } + } + String[] historyValues = new String[] { translate("disable.history"), translate("password.after","1"), translate("password.after","2"), translate("password.after","5"), translate("password.after","10"), translate("password.after","15")}; + if(!hasVal) { + historyKeys = append(historyKeys, selectedVal); + historyValues = append(historyValues, selectedVal); + } + historyEl = uifactory.addDropdownSingleselect("password.history", "password.history", formLayout, historyKeys, historyValues, null); + historyEl.select(selectedVal, true); + + updateLettersUI(); + updateDigitsSpecialsUI(); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("save", buttonsCont); + previewLink = uifactory.addFormLink("admin.syntax.preview", buttonsCont, Link.BUTTON); + previewLink.setIconLeftCSS("o_icon o_icon_preview"); + previewLink.getComponent().setSuppressDirtyFormWarning(true); + } + + private String[] append(String[] array, String val) { + String[] newArray = new String[array.length + 1]; + System.arraycopy(array, 0, newArray, 0, array.length); + newArray[array.length] = val; + return newArray; + } + + @Override + protected void propagateDirtinessToContainer(FormItem fiSrc, FormEvent fe) { + if (fiSrc != this.previewLink) { + super.propagateDirtinessToContainer(fiSrc, fe); + } + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == lettersEl) { + updateLettersUI(); + } else if (source == digitsAndSpecialsEl) { + updateDigitsSpecialsUI(); + } else if (source == previewLink) { + doOpenPreview(ureq); + } + super.formInnerEvent(ureq, source, event); + } + + private void updateLettersUI() { + boolean validateSeparately = lettersEl.isOneSelected() && VALIDATE_SEPARATELY.equals(lettersEl.getSelectedKey()); + lettersUppercaseEl.setVisible(validateSeparately); + lettersLowercaseEl.setVisible(validateSeparately); + } + + private void updateDigitsSpecialsUI() { + boolean validateSeparately = digitsAndSpecialsEl.isOneSelected() + && VALIDATE_SEPARATELY.equals(digitsAndSpecialsEl.getSelectedKey()); + digitsEl.setVisible(validateSeparately); + specialsEl.setVisible(validateSeparately); + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if (source == previewCtrl) { + cmc.deactivate(); + cleanUp(); + } else if (source == cmc) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(previewCtrl); + removeAsListenerAndDispose(cmc); + previewCtrl = null; + cmc = null; + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + allOk &= validateInteger(minLengthEl, 1); + allOk &= validateInteger(maxLengthEl, 1); + if (allOk) { + int min = Integer.parseInt(minLengthEl.getValue()); + int max = Integer.parseInt(maxLengthEl.getValue()); + if (max < min) { + maxLengthEl.setErrorKey("error.password.length.lower", null); + allOk = false; + } + } + + historyEl.clearError(); + if(!historyEl.isOneSelected()) { + historyEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + return allOk; + } + + @Override + protected void formOK(UserRequest ureq) { + PasswordValidationConfig config = getPasswordValidationConfig(); + loginModule.setPasswordMinLength(config.getPasswordMinLength()); + loginModule.setPasswordMaxLength(config.getPasswordMaxLength()); + loginModule.setPasswordLetters(config.getPasswordLetters()); + loginModule.setPasswordLettersUppercase(config.getPasswordLettersUppercase()); + loginModule.setPasswordLettersLowercase(config.getPasswordLettersLowercase()); + loginModule.setPasswordDigitsAndSpecialSigns(config.getPasswordDigitsAndSpecialSigns()); + loginModule.setPasswordDigits(config.getPasswordDigits()); + loginModule.setPasswordSpecialSigns(config.getPasswordSpecialSigns()); + loginModule.setPasswordUsernameForbidden(config.isPasswordUsernameForbidden()); + loginModule.setPasswordFirstnameForbidden(config.isPasswordFirstnameForbidden()); + loginModule.setPasswordLastnameForbidden(config.isPasswordLastnameForbidden()); + loginModule.setPasswordHistory(config.getPasswordHistory()); + + log.info("Passwort syntax validation configuration changed by " + getIdentity()); + } + + private PasswordValidationConfig getPasswordValidationConfig() { + Builder builder = PasswordValidationConfig.builder(); + + int passwordMinLength = Integer.parseInt(minLengthEl.getValue()); + builder.withPasswordMinLength(passwordMinLength); + + int passwordMaxLength = Integer.parseInt(maxLengthEl.getValue()); + builder.withPasswordMaxLength(passwordMaxLength); + + String passwordLetters = lettersEl.isOneSelected() + ? lettersEl.getSelectedKey() + : DISABLED; + builder.withPasswordLetters(passwordLetters); + + String passwordLettersUppercase = VALIDATE_SEPARATELY.equals(passwordLetters) + && lettersUppercaseEl.isOneSelected() + ? lettersUppercaseEl.getSelectedKey() + : DISABLED; + builder.withPasswordLettersUppercase(passwordLettersUppercase); + + String passwordLettersLowercase = VALIDATE_SEPARATELY.equals(passwordLetters) + && lettersLowercaseEl.isOneSelected() + ? lettersLowercaseEl.getSelectedKey() + : DISABLED; + builder.withPasswordLettersLowercase(passwordLettersLowercase); + + String passwordDigitsAndSpecialSigns = digitsAndSpecialsEl.isOneSelected() + ? digitsAndSpecialsEl.getSelectedKey() + : DISABLED; + builder.withPasswordDigitsAndSpecialSigns(passwordDigitsAndSpecialSigns); + + String passwordDigits = VALIDATE_SEPARATELY.equals(passwordDigitsAndSpecialSigns) + && digitsEl.isOneSelected() + ? digitsEl.getSelectedKey() + : DISABLED; + builder.withPasswordDigits(passwordDigits); + + String passwordSpecialSigns = VALIDATE_SEPARATELY.equalsIgnoreCase(passwordDigitsAndSpecialSigns) + && specialsEl.isOneSelected() + ? specialsEl.getSelectedKey() + : DISABLED; + builder.withPasswordSpecialSigns(passwordSpecialSigns); + + Collection<String> forbiddenValuesKeys = forbiddenValuesEl.getSelectedKeys(); + builder.withPasswordUsernameForbidden(forbiddenValuesKeys.contains(FORBIDDEN_USERNAME)); + builder.withPasswordFirstnameForbidden(forbiddenValuesKeys.contains(FORBIDDEN_FIRSTNAME)); + builder.withPasswordLastnameForbidden(forbiddenValuesKeys.contains(FORBIDDEN_LASTNAME)); + + int history = Integer.parseInt(historyEl.getSelectedKey()); + builder.withPasswordHistory(history); + + return builder.build(); + } + + private void doOpenPreview(UserRequest ureq) { + boolean allOk = validateFormLogic(ureq); + + if (allOk) { + PasswordValidationConfig config = getPasswordValidationConfig(); + ValidationRulesProvider rulesProvider = passwordValidationRulesFactory.createRules(config); + SyntaxValidator validator = new SyntaxValidator(rulesProvider, true); + previewCtrl = new PasswordPreviewController(ureq, getWindowControl(), validator); + listenTo(previewCtrl); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), + previewCtrl.getInitialComponent(), true, translate("admin.syntax.preview.title")); + cmc.activate(); + listenTo(cmc); + } + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/login/ui/_content/admin.html b/src/main/java/org/olat/login/ui/_content/admin.html new file mode 100644 index 00000000000..5da6ca9b652 --- /dev/null +++ b/src/main/java/org/olat/login/ui/_content/admin.html @@ -0,0 +1,7 @@ +<div class="clearfix"> + $r.render("segments")<br/> + + #if($r.available("segmentCmp")) + $r.render("segmentCmp") + #end +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/login/validation/AtLeastCharacterRule.java b/src/main/java/org/olat/login/validation/AtLeastCharacterRule.java new file mode 100644 index 00000000000..246d395987a --- /dev/null +++ b/src/main/java/org/olat/login/validation/AtLeastCharacterRule.java @@ -0,0 +1,63 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.function.Predicate; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 13 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class AtLeastCharacterRule extends DescriptionRule { + + private final Predicate<Character> filter; + private final int minCount; + + AtLeastCharacterRule(ValidationDescription description, Predicate<Character> filter, int minCount) { + super(description); + this.filter = filter; + this.minCount = minCount; + } + + @Override + public boolean validate(String value, Identity identity) { + int count = 0; + for (int i = 0; i < value.length(); i++) { + char character = value.charAt(i); + if (filter.test(character)) { + count++; + if (count >= minCount) { + return true; + } + } + } + return false; + } + + @Override + public boolean isIdentityRule() { + return false; + } + +} diff --git a/src/main/java/org/olat/login/validation/DescriptionRule.java b/src/main/java/org/olat/login/validation/DescriptionRule.java new file mode 100644 index 00000000000..4e8182efdab --- /dev/null +++ b/src/main/java/org/olat/login/validation/DescriptionRule.java @@ -0,0 +1,41 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +/** + * + * Initial date: 19 Jun 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +abstract class DescriptionRule implements ValidationRule { + + private final ValidationDescription description; + + DescriptionRule(ValidationDescription description) { + this.description = description; + } + + @Override + public ValidationDescription getDescription() { + return description; + } + +} diff --git a/src/main/java/org/olat/login/validation/HistoryRule.java b/src/main/java/org/olat/login/validation/HistoryRule.java new file mode 100644 index 00000000000..247565ed821 --- /dev/null +++ b/src/main/java/org/olat/login/validation/HistoryRule.java @@ -0,0 +1,73 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.BaseSecurityModule; +import org.olat.basesecurity.manager.AuthenticationDAO; +import org.olat.core.CoreSpringFactory; +import org.olat.core.id.Identity; +import org.olat.ldap.LDAPLoginModule; +import org.olat.ldap.ui.LDAPAuthenticationController; + +/** + * + * Initial date: 21 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class HistoryRule extends DescriptionRule { + + private int historyLength; + + HistoryRule(ValidationDescription description, int historyLength) { + super(description); + this.historyLength = historyLength; + } + + @Override + public boolean validate(String value, Identity identity) { + BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); + + boolean ok = true; + // Is this the right place to check if the user is logged in with LDAP? + // What happens if someone changes the password of someone else? + // Further, the description is shown even if the user is logged in with LDAP, + // although this rule is ignored in that case. + if (notAutenticatedWithLDAP(identity)) { + ok = securityManager.checkCredentialHistory(identity, BaseSecurityModule.getDefaultAuthProviderIdentifier(), + value, historyLength); + } + return ok; + } + + private boolean notAutenticatedWithLDAP(Identity identity) { + LDAPLoginModule ldapLoginModule = CoreSpringFactory.getImpl(LDAPLoginModule.class); + AuthenticationDAO authenticationDao = CoreSpringFactory.getImpl(AuthenticationDAO.class); + return !ldapLoginModule.isLDAPEnabled() + || !authenticationDao.hasAuthentication(identity, LDAPAuthenticationController.PROVIDER_LDAP); + } + + @Override + public boolean isIdentityRule() { + return true; + } + +} diff --git a/src/main/java/org/olat/login/validation/IdentityValueForbiddenRule.java b/src/main/java/org/olat/login/validation/IdentityValueForbiddenRule.java new file mode 100644 index 00000000000..2b8fb758612 --- /dev/null +++ b/src/main/java/org/olat/login/validation/IdentityValueForbiddenRule.java @@ -0,0 +1,57 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.function.Function; + +import org.olat.core.id.Identity; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 14 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class IdentityValueForbiddenRule extends DescriptionRule { + + private final Function<Identity, String> forbiddenValue; + + IdentityValueForbiddenRule(ValidationDescription description, Function<Identity, String> forbiddenValue) { + super(description); + this.forbiddenValue = forbiddenValue; + } + + @Override + public boolean validate(String value, Identity identity) { + if (identity == null) return true; + + String identityValue = forbiddenValue.apply(identity); + if (!StringHelper.containsNonWhitespace(identityValue)) return true; + + return !value.toLowerCase().contains(identityValue.toLowerCase()); + } + + @Override + public boolean isIdentityRule() { + return true; + } + +} diff --git a/src/main/java/org/olat/login/validation/OppositeRule.java b/src/main/java/org/olat/login/validation/OppositeRule.java new file mode 100644 index 00000000000..380b7cc40e2 --- /dev/null +++ b/src/main/java/org/olat/login/validation/OppositeRule.java @@ -0,0 +1,54 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.core.id.Identity; + +/** + * Switches a valid rule to an invalid and an invalid rule to a valid rule. + * + * Initial date: 14 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class OppositeRule implements ValidationRule { + + private final ValidationRule rule; + + OppositeRule(ValidationRule rule) { + this.rule = rule; + } + + @Override + public boolean validate(String value, Identity identity) { + return !rule.validate(value, null); + } + + @Override + public ValidationDescription getDescription() { + return rule.getDescription(); + } + + @Override + public boolean isIdentityRule() { + return rule.isIdentityRule(); + } + +} diff --git a/src/main/java/org/olat/login/validation/PasswordValidationConfig.java b/src/main/java/org/olat/login/validation/PasswordValidationConfig.java new file mode 100644 index 00000000000..d65f39283b5 --- /dev/null +++ b/src/main/java/org/olat/login/validation/PasswordValidationConfig.java @@ -0,0 +1,192 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +/** + * + * Initial date: 16 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class PasswordValidationConfig { + + private final int passwordMinLength; + private final int passwordMaxLength; + private final String passwordLetters; + private final String passwordLettersUppercase; + private final String passwordLettersLowercase; + private final String passwordDigitsAndSpecialSigns; + private final String passwordDigits; + private final String passwordSpecialSigns; + private final boolean passwordUsernameForbidden; + private final boolean passwordFirstnameForbidden; + private final boolean passwordLastnameForbidden; + private final int passwordHistory; + + private PasswordValidationConfig(Builder builder) { + this.passwordMinLength = builder.passwordMinLength; + this.passwordMaxLength = builder.passwordMaxLength; + this.passwordLetters = builder.passwordLetters; + this.passwordLettersUppercase = builder.passwordLettersUppercase; + this.passwordLettersLowercase = builder.passwordLettersLowercase; + this.passwordDigitsAndSpecialSigns = builder.passwordDigitsAndSpecialSigns; + this.passwordDigits = builder.passwordDigits; + this.passwordSpecialSigns = builder.passwordSpecialSigns; + this.passwordUsernameForbidden = builder.passwordUsernameForbidden; + this.passwordFirstnameForbidden = builder.passwordFirstnameForbidden; + this.passwordLastnameForbidden = builder.passwordLastnameForbidden; + this.passwordHistory = builder.passwordHistory; + } + + public int getPasswordMinLength() { + return passwordMinLength; + } + + public int getPasswordMaxLength() { + return passwordMaxLength; + } + + public String getPasswordLetters() { + return passwordLetters; + } + + public String getPasswordLettersUppercase() { + return passwordLettersUppercase; + } + + public String getPasswordLettersLowercase() { + return passwordLettersLowercase; + } + + public String getPasswordDigitsAndSpecialSigns() { + return passwordDigitsAndSpecialSigns; + } + + public String getPasswordDigits() { + return passwordDigits; + } + + public String getPasswordSpecialSigns() { + return passwordSpecialSigns; + } + + public boolean isPasswordUsernameForbidden() { + return passwordUsernameForbidden; + } + + public boolean isPasswordFirstnameForbidden() { + return passwordFirstnameForbidden; + } + + public boolean isPasswordLastnameForbidden() { + return passwordLastnameForbidden; + } + + public int getPasswordHistory() { + return passwordHistory; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private int passwordMinLength; + private int passwordMaxLength; + private String passwordLetters; + private String passwordLettersUppercase; + private String passwordLettersLowercase; + private String passwordDigitsAndSpecialSigns; + private String passwordDigits; + private String passwordSpecialSigns; + private boolean passwordUsernameForbidden; + private boolean passwordFirstnameForbidden; + private boolean passwordLastnameForbidden; + private int passwordHistory; + + private Builder() { + } + + public Builder withPasswordMinLength(int passwordMinLength) { + this.passwordMinLength = passwordMinLength; + return this; + } + + public Builder withPasswordMaxLength(int passwordMaxLength) { + this.passwordMaxLength = passwordMaxLength; + return this; + } + + public Builder withPasswordLetters(String passwordLetters) { + this.passwordLetters = passwordLetters; + return this; + } + + public Builder withPasswordLettersUppercase(String passwordLettersUppercase) { + this.passwordLettersUppercase = passwordLettersUppercase; + return this; + } + + public Builder withPasswordLettersLowercase(String passwordLettersLowercase) { + this.passwordLettersLowercase = passwordLettersLowercase; + return this; + } + + public Builder withPasswordDigitsAndSpecialSigns(String passwordDigitsAndSpecialSigns) { + this.passwordDigitsAndSpecialSigns = passwordDigitsAndSpecialSigns; + return this; + } + + public Builder withPasswordDigits(String passwordDigits) { + this.passwordDigits = passwordDigits; + return this; + } + + public Builder withPasswordSpecialSigns(String passwordSpecialSigns) { + this.passwordSpecialSigns = passwordSpecialSigns; + return this; + } + + public Builder withPasswordUsernameForbidden(boolean passwordUsernameForbidden) { + this.passwordUsernameForbidden = passwordUsernameForbidden; + return this; + } + + public Builder withPasswordFirstnameForbidden(boolean passwordFirstnameForbidden) { + this.passwordFirstnameForbidden = passwordFirstnameForbidden; + return this; + } + + public Builder withPasswordLastnameForbidden(boolean passwordLastnameForbidden) { + this.passwordLastnameForbidden = passwordLastnameForbidden; + return this; + } + + public Builder withPasswordHistory(int passwordHistory) { + this.passwordHistory = passwordHistory; + return this; + } + + public PasswordValidationConfig build() { + return new PasswordValidationConfig(this); + } + } + +} diff --git a/src/main/java/org/olat/login/validation/PasswordValidationRuleFactory.java b/src/main/java/org/olat/login/validation/PasswordValidationRuleFactory.java new file mode 100644 index 00000000000..0721f1e50a9 --- /dev/null +++ b/src/main/java/org/olat/login/validation/PasswordValidationRuleFactory.java @@ -0,0 +1,192 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import static java.util.regex.Pattern.UNICODE_CHARACTER_CLASS; + +import java.util.Locale; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.olat.core.gui.translator.Translator; +import org.olat.core.id.Identity; +import org.olat.core.util.Util; +import org.olat.login.LoginModule; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +@Service +public class PasswordValidationRuleFactory { + + public ValidationRule createVisibleCharactersRule(int min, int max) { + ValidationDescription description = createDescription("password.rule.length", min, max); + Pattern pattern = Pattern.compile("^\\p{Graph}{" + min + "," + max + "}$", UNICODE_CHARACTER_CLASS); + return new RegexRule(description, pattern); + } + + public ValidationRule createAtLeastLettersRule(int min) { + ValidationDescription description = createDescription("password.rule.at.least.letters", min); + return new AtLeastCharacterRule(description, Character::isLetter, min); + } + + public ValidationRule createAtLeastLettersUppercaseRule(int min) { + ValidationDescription description = createDescription("password.rule.at.least.letters.uppercase", min); + return new AtLeastCharacterRule(description, Character::isUpperCase, min); + } + + public ValidationRule createAtLeastLettersLowercaseRule(int min) { + ValidationDescription description = createDescription("password.rule.at.least.letters.lowercase", min); + return new AtLeastCharacterRule(description, Character::isLowerCase, min); + } + + public ValidationRule createAtLeastDigitsRule(int min) { + ValidationDescription description = createDescription("password.rule.at.least.digits", min); + return new AtLeastCharacterRule(description, Character::isDigit, min); + } + + public ValidationRule createAtLeastSpecialSignsRule(int min) { + ValidationDescription description = createDescription("password.rule.at.least.specials", min); + // at least 2: .*\\W.*\\W.* + String regex = Stream.generate(() -> ".*").limit(min + 1).collect(Collectors.joining("\\W")); + Pattern pattern = Pattern.compile(regex, UNICODE_CHARACTER_CLASS); + return new RegexRule(description, pattern); + } + + public ValidationRule createAtLeastDigitsOrSpecialSignsRule(int min) { + ValidationDescription description = createDescription("password.rule.at.least.digits.specials", min); + String regex = Stream.generate(() -> ".*").limit(min + 1).collect(Collectors.joining("[\\d|\\W]")); + Pattern pattern = Pattern.compile(regex, UNICODE_CHARACTER_CLASS); + return new RegexRule(description, pattern); + } + + public ValidationRule createLettersPermittedRule() { + ValidationDescription description = createDescription("password.rule.permitted.letters"); + return new TrueRule(description); + } + + public ValidationRule createLettersUppercasePermittedRule() { + ValidationDescription description = createDescription("password.rule.permitted.letters.uppercase"); + return new TrueRule(description); + } + + public ValidationRule createLettersLowercasePermittedRule() { + ValidationDescription description = createDescription("password.rule.permitted.letters.lowercase"); + return new TrueRule(description); + } + + public ValidationRule createDigitsAndSpecialSignsPermittedRule() { + ValidationDescription description = createDescription("password.rule.permitted.digits.specials"); + return new TrueRule(description); + } + + public ValidationRule createDigitsPermittedRule() { + ValidationDescription description = createDescription("password.rule.permitted.digits"); + return new TrueRule(description); + } + + public ValidationRule createSpecialSignsPermittedRule() { + ValidationDescription description = createDescription("password.rule.permitted.specials"); + return new TrueRule(description); + } + + public ValidationRule createLettersForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.letters"); + return new OppositeRule(new AtLeastCharacterRule(description, Character::isLetter, 1)); + } + + public ValidationRule createLettersUppercaseForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.letters.uppercase"); + return new OppositeRule(new AtLeastCharacterRule(description, Character::isUpperCase, 1)); + } + + public ValidationRule createLettersLowercaseForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.letters.lowercase"); + return new OppositeRule(new AtLeastCharacterRule(description, Character::isLowerCase, 1)); + } + + public ValidationRule createDigitsForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.digits"); + return new OppositeRule(new AtLeastCharacterRule(description, Character::isDigit, 1)); + } + + public ValidationRule createSpecialSignsForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.specials"); + Pattern pattern = Pattern.compile(".*\\W+.*", UNICODE_CHARACTER_CLASS); + return new OppositeRule(new RegexRule(description, pattern)); + } + + public ValidationRule createDigitsAndSpecialSignsForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.specials"); + Pattern pattern = Pattern.compile(".*[\\W|\\d]+.*", UNICODE_CHARACTER_CLASS); + return new OppositeRule(new RegexRule(description, pattern)); + } + + public ValidationRule createUsernameForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.username"); + Function<Identity, String> forbiddenValue = i -> i.getName(); + return new IdentityValueForbiddenRule(description, forbiddenValue); + } + + public ValidationRule createUserFirstnameForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.user.firstname"); + Function<Identity, String> forbiddenValue = i -> i.getUser().getFirstName(); + return new IdentityValueForbiddenRule(description, forbiddenValue); + } + + public ValidationRule createUserLastnameForbiddenRule() { + ValidationDescription description = createDescription("password.rule.forbidden.user.lastname"); + Function<Identity, String> forbiddenValue = i -> i.getUser().getLastName(); + return new IdentityValueForbiddenRule(description, forbiddenValue); + } + + public ValidationRule createHistoryRule(int numberChanges) { + ValidationDescription description = createDescription("password.rule.history"); + return new HistoryRule(description, numberChanges); + } + + private ValidationDescription createDescription(String i18nKey) { + return new TranslatedDescription(createTranslator(), i18nKey); + } + + private ValidationDescription createDescription(String i18nKey, int arg) { + return createDescription(i18nKey, new String[] { String.valueOf(arg) } ); + } + + private ValidationDescription createDescription(String i18nKey, int arg1, int arg2) { + return createDescription(i18nKey, new String[] { String.valueOf(arg1), String.valueOf(arg2) } ); + } + + private ValidationDescription createDescription(String i18nKey, String[] args) { + return new TranslatedDescription(createTranslator(), i18nKey, args); + } + + protected Translator createTranslator() { + // The user locale is set later, so use the default locale to construct the translator. + return Util.createPackageTranslator(LoginModule.class, Locale.getDefault()); + } + +} diff --git a/src/main/java/org/olat/login/validation/PasswordValidationRulesFactory.java b/src/main/java/org/olat/login/validation/PasswordValidationRulesFactory.java new file mode 100644 index 00000000000..d5e09467ce7 --- /dev/null +++ b/src/main/java/org/olat/login/validation/PasswordValidationRulesFactory.java @@ -0,0 +1,178 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.login.LoginModule; +import org.olat.login.validation.PasswordValidationConfig.Builder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +@Service +public class PasswordValidationRulesFactory { + + @Autowired + private PasswordValidationRuleFactory ruleFactory; + @Autowired + private LoginModule loginModule; + + public ValidationRulesProvider createRules() { + Builder configBuilder = PasswordValidationConfig.builder(); + configBuilder.withPasswordMinLength(loginModule.getPasswordMinLength()); + configBuilder.withPasswordMaxLength(loginModule.getPasswordMaxLength()); + configBuilder.withPasswordLetters(loginModule.getPasswordLetters()); + configBuilder.withPasswordLettersUppercase(loginModule.getPasswordLettersUppercase()); + configBuilder.withPasswordLettersLowercase(loginModule.getPasswordLettersLowercase()); + configBuilder.withPasswordDigitsAndSpecialSigns(loginModule.getPasswordDigitsAndSpecialSigns()); + configBuilder.withPasswordDigits(loginModule.getPasswordDigits()); + configBuilder.withPasswordSpecialSigns(loginModule.getPasswordSpecialSigns()); + configBuilder.withPasswordUsernameForbidden(loginModule.isPasswordUsernameForbidden()); + configBuilder.withPasswordFirstnameForbidden(loginModule.isPasswordFirstnameForbidden()); + configBuilder.withPasswordLastnameForbidden(loginModule.isPasswordLastnameForbidden()); + configBuilder.withPasswordHistory(loginModule.getPasswordHistory()); + return createRules(configBuilder.build()); + } + + public ValidationRulesProvider createRules(PasswordValidationConfig config) { + ValidationRulesProviderBuilder providerBuilder = new ValidationRulesProviderBuilder(); + + ValidationRule visibleCharactersRule = ruleFactory.createVisibleCharactersRule(config.getPasswordMinLength(), + config.getPasswordMaxLength()); + providerBuilder.add(visibleCharactersRule); + + if (LoginModule.VALIDATE_SEPARATELY.equals(config.getPasswordLetters())) { + ValidationRule lettersUppercaseRule = createLettersUppercaseRule(config.getPasswordLettersUppercase()); + providerBuilder.add(lettersUppercaseRule); + ValidationRule lettersLowercaseRule = createLettersLowercaseRule(config.getPasswordLettersLowercase()); + providerBuilder.add(lettersLowercaseRule); + } else { + ValidationRule lettersRule = createLettersRule(config.getPasswordLetters()); + providerBuilder.add(lettersRule); + } + + if (LoginModule.VALIDATE_SEPARATELY.equals(config.getPasswordDigitsAndSpecialSigns())) { + ValidationRule digitsRule = createDigitsRule(config.getPasswordDigits()); + providerBuilder.add(digitsRule); + ValidationRule specialSignsRule = createSpecialSignsRule(config.getPasswordSpecialSigns()); + providerBuilder.add(specialSignsRule); + } else { + ValidationRule digitsOrSpecialSignsRule = createDigitsAndSpecialSignsRule(config.getPasswordDigitsAndSpecialSigns()); + providerBuilder.add(digitsOrSpecialSignsRule); + } + + if (config.isPasswordUsernameForbidden()) { + ValidationRule usernameForbiddenRule = ruleFactory.createUsernameForbiddenRule(); + providerBuilder.add(usernameForbiddenRule); + } + if (config.isPasswordFirstnameForbidden()) { + ValidationRule userFirstnameForbiddenRule = ruleFactory.createUserFirstnameForbiddenRule(); + providerBuilder.add(userFirstnameForbiddenRule); + } + if (config.isPasswordLastnameForbidden()) { + ValidationRule userLastnameForbiddenRule = ruleFactory.createUserLastnameForbiddenRule(); + providerBuilder.add(userLastnameForbiddenRule); + } + + if (config.getPasswordHistory() > 0) { + ValidationRule historyRule = ruleFactory.createHistoryRule(config.getPasswordHistory()); + providerBuilder.add(historyRule); + } + + return providerBuilder.create(); + } + + private ValidationRule createLettersRule(String passwordLetters) { + switch (passwordLetters) { + case LoginModule.AT_LEAST_1: return ruleFactory.createAtLeastLettersRule(1); + case LoginModule.AT_LEAST_2: return ruleFactory.createAtLeastLettersRule(2); + case LoginModule.AT_LEAST_3: return ruleFactory.createAtLeastLettersRule(3); + case LoginModule.FORBIDDEN: return ruleFactory.createLettersForbiddenRule(); + case LoginModule.DISABLED: + default: + return ruleFactory.createLettersPermittedRule(); + } + } + + private ValidationRule createLettersUppercaseRule(String passwordLettersUppercase) { + switch (passwordLettersUppercase) { + case LoginModule.AT_LEAST_1: return ruleFactory.createAtLeastLettersUppercaseRule(1); + case LoginModule.AT_LEAST_2: return ruleFactory.createAtLeastLettersUppercaseRule(2); + case LoginModule.AT_LEAST_3: return ruleFactory.createAtLeastLettersUppercaseRule(3); + case LoginModule.FORBIDDEN: return ruleFactory.createLettersUppercaseForbiddenRule(); + case LoginModule.DISABLED: + default: + return ruleFactory.createLettersPermittedRule(); + } + } + + private ValidationRule createLettersLowercaseRule(String passwordLettersLowercase) { + switch (passwordLettersLowercase) { + case LoginModule.AT_LEAST_1: return ruleFactory.createAtLeastLettersLowercaseRule(1); + case LoginModule.AT_LEAST_2: return ruleFactory.createAtLeastLettersLowercaseRule(2); + case LoginModule.AT_LEAST_3: return ruleFactory.createAtLeastLettersLowercaseRule(3); + case LoginModule.FORBIDDEN: return ruleFactory.createLettersLowercaseForbiddenRule(); + case LoginModule.DISABLED: + default: + return ruleFactory.createLettersPermittedRule(); + } + } + + private ValidationRule createDigitsAndSpecialSignsRule(String passwordDigitsOrSpecialSigns) { + switch (passwordDigitsOrSpecialSigns) { + case LoginModule.AT_LEAST_1: return ruleFactory.createAtLeastDigitsOrSpecialSignsRule(1); + case LoginModule.AT_LEAST_2: return ruleFactory.createAtLeastDigitsOrSpecialSignsRule(2); + case LoginModule.AT_LEAST_3: return ruleFactory.createAtLeastDigitsOrSpecialSignsRule(3); + case LoginModule.FORBIDDEN: return ruleFactory.createDigitsAndSpecialSignsForbiddenRule(); + case LoginModule.DISABLED: + default: + return ruleFactory.createDigitsAndSpecialSignsPermittedRule(); + } + } + + private ValidationRule createDigitsRule(String passwordDigits) { + switch (passwordDigits) { + case LoginModule.AT_LEAST_1: return ruleFactory.createAtLeastDigitsRule(1); + case LoginModule.AT_LEAST_2: return ruleFactory.createAtLeastDigitsRule(2); + case LoginModule.AT_LEAST_3: return ruleFactory.createAtLeastDigitsRule(3); + case LoginModule.FORBIDDEN: return ruleFactory.createDigitsForbiddenRule(); + case LoginModule.DISABLED: + default: + return ruleFactory.createDigitsPermittedRule(); + } + } + + private ValidationRule createSpecialSignsRule(String passwordSpecialSigns) { + switch (passwordSpecialSigns) { + case LoginModule.AT_LEAST_1: return ruleFactory.createAtLeastSpecialSignsRule(1); + case LoginModule.AT_LEAST_2: return ruleFactory.createAtLeastSpecialSignsRule(2); + case LoginModule.AT_LEAST_3: return ruleFactory.createAtLeastSpecialSignsRule(3); + case LoginModule.FORBIDDEN: return ruleFactory.createSpecialSignsForbiddenRule(); + case LoginModule.DISABLED: + default: + return ruleFactory.createSpecialSignsPermittedRule(); + } + } + +} diff --git a/src/main/java/org/olat/login/validation/RegexRule.java b/src/main/java/org/olat/login/validation/RegexRule.java new file mode 100644 index 00000000000..1c9e99437e0 --- /dev/null +++ b/src/main/java/org/olat/login/validation/RegexRule.java @@ -0,0 +1,55 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.regex.Pattern; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 13 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class RegexRule extends DescriptionRule { + + private final Pattern pattern; + + RegexRule(ValidationDescription description, String pattern) { + this(description, Pattern.compile(pattern)); + } + + RegexRule(ValidationDescription description, Pattern pattern) { + super(description); + this.pattern = pattern; + } + + @Override + public boolean validate(String value, Identity identity) { + return pattern.matcher(value).matches(); + } + + @Override + public boolean isIdentityRule() { + return false; + } + +} diff --git a/src/main/java/org/olat/login/validation/SyntaxValidator.java b/src/main/java/org/olat/login/validation/SyntaxValidator.java new file mode 100644 index 00000000000..8c6e36b09f3 --- /dev/null +++ b/src/main/java/org/olat/login/validation/SyntaxValidator.java @@ -0,0 +1,108 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class SyntaxValidator { + + private final List<ValidationRule> rules; + private final boolean validateAll; + + public SyntaxValidator(ValidationRulesProvider provider, boolean validateAll) { + this.rules = provider.getRules(); + this.validateAll = validateAll; + } + + public List<ValidationDescription> getAllDescriptions() { + return getAllDescriptions(false); + } + + public List<ValidationDescription> getAllDescriptions(boolean ignoreIdentityValidations) { + return rules.stream() + .filter(identityRuleFilter(ignoreIdentityValidations)) + .map(ValidationRule::getDescription) + .collect(Collectors.toList()); + } + + private Predicate<? super ValidationRule> identityRuleFilter(boolean ignoreIdentityRules) { + return rule -> ignoreIdentityRules? !rule.isIdentityRule(): true; + } + + public ValidationResult validate(String value) { + ValidationResultImpl result = new ValidationResultImpl(); + for (ValidationRule rule : rules) { + if (!rule.isIdentityRule()) { + if (!rule.validate(value, null)) { + result.addInvalidRule(rule.getDescription()); + if (!validateAll) { + return result; + } + } + } + } + return result; + } + + public ValidationResult validate(String value, Identity identity) { + ValidationResultImpl result = new ValidationResultImpl(); + for (ValidationRule rule : rules) { + if (!rule.validate(value, identity)) { + result.addInvalidRule(rule.getDescription()); + if (!validateAll) { + return result; + } + } + } + return result; + } + + private static class ValidationResultImpl implements ValidationResult { + + private final List<ValidationDescription> invalidDescription = new ArrayList<>(); + + @Override + public boolean isValid() { + return invalidDescription.isEmpty(); + } + + @Override + public List<ValidationDescription> getInvalidDescriptions() { + return invalidDescription; + } + + public void addInvalidRule(ValidationDescription description) { + invalidDescription.add(description); + } + + } + +} diff --git a/src/main/java/org/olat/login/validation/TranslatedDescription.java b/src/main/java/org/olat/login/validation/TranslatedDescription.java new file mode 100644 index 00000000000..b8486fee43f --- /dev/null +++ b/src/main/java/org/olat/login/validation/TranslatedDescription.java @@ -0,0 +1,54 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.Locale; + +import org.olat.core.gui.translator.Translator; + +/** + * + * Initial date: 13 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class TranslatedDescription implements ValidationDescription { + + private final Translator translator; + private final String i18nKey; + private final String[] args; + + public TranslatedDescription(Translator translator, String i18nKey) { + this(translator, i18nKey, null); + } + + public TranslatedDescription(Translator translator, String i18nKey, String[] args) { + this.translator = translator; + this.i18nKey = i18nKey; + this.args = args; + } + + @Override + public String getText(Locale locale) { + translator.setLocale(locale); + return translator.translate(i18nKey, args); + } + +} diff --git a/src/main/java/org/olat/login/validation/TrueRule.java b/src/main/java/org/olat/login/validation/TrueRule.java new file mode 100644 index 00000000000..58b35b9118c --- /dev/null +++ b/src/main/java/org/olat/login/validation/TrueRule.java @@ -0,0 +1,46 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 20 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class TrueRule extends DescriptionRule { + + public TrueRule(ValidationDescription description) { + super(description); + } + + @Override + public boolean validate(String value, Identity identity) { + return true; + } + + @Override + public boolean isIdentityRule() { + return false; + } + +} diff --git a/src/main/java/org/olat/login/validation/UsernameBlackListRule.java b/src/main/java/org/olat/login/validation/UsernameBlackListRule.java new file mode 100644 index 00000000000..1d5c6ee29bf --- /dev/null +++ b/src/main/java/org/olat/login/validation/UsernameBlackListRule.java @@ -0,0 +1,49 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.id.Identity; +import org.olat.user.UserModule; + +/** + * + * Initial date: 19 Jun 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class UsernameBlackListRule extends DescriptionRule { + + UsernameBlackListRule(ValidationDescription description) { + super(description); + } + + @Override + public boolean validate(String value, Identity identity) { + UserModule userModule = CoreSpringFactory.getImpl(UserModule.class); + return !userModule.isLoginOnBlacklist(value); + } + + @Override + public boolean isIdentityRule() { + return false; + } + +} diff --git a/src/main/java/org/olat/login/validation/UsernameInUseRule.java b/src/main/java/org/olat/login/validation/UsernameInUseRule.java new file mode 100644 index 00000000000..cae773901b6 --- /dev/null +++ b/src/main/java/org/olat/login/validation/UsernameInUseRule.java @@ -0,0 +1,49 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.basesecurity.BaseSecurity; +import org.olat.core.CoreSpringFactory; +import org.olat.core.id.Identity; + +/** + * + * Initial date: 19 Jun 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class UsernameInUseRule extends DescriptionRule { + + UsernameInUseRule(ValidationDescription description) { + super(description); + } + + @Override + public boolean validate(String value, Identity identity) { + BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); + return securityManager.findIdentityByName(value) == null; + } + + @Override + public boolean isIdentityRule() { + return false; + } + +} diff --git a/src/main/java/org/olat/login/validation/UsernameValidationRulesFactory.java b/src/main/java/org/olat/login/validation/UsernameValidationRulesFactory.java new file mode 100644 index 00000000000..78727db8a95 --- /dev/null +++ b/src/main/java/org/olat/login/validation/UsernameValidationRulesFactory.java @@ -0,0 +1,73 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.Locale; + +import org.olat.core.gui.translator.Translator; +import org.olat.core.util.Util; +import org.olat.login.LoginModule; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 19 Jun 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +@Service +public class UsernameValidationRulesFactory { + + @Autowired + private LoginModule loginModule; + + public ValidationRulesProvider createRules() { + ValidationRulesProviderBuilder providerBuilder = new ValidationRulesProviderBuilder(); + providerBuilder.add(createUsernameSyntaxRule()); + providerBuilder.add(createBlackListRule()); + providerBuilder.add(createUsernameExistsRule()); + return providerBuilder.create(); + } + + protected ValidationRule createUsernameSyntaxRule() { + ValidationDescription description = createDescription("username.rule.syntax"); + return new RegexRule(description, loginModule.getUsernamePattern()); + } + + protected ValidationRule createBlackListRule() { + ValidationDescription description = createDescription("username.rule.blacklist"); + return new UsernameBlackListRule(description); + } + + private ValidationRule createUsernameExistsRule() { + ValidationDescription description = createDescription("username.rule.in.use"); + return new UsernameInUseRule(description); + } + + private ValidationDescription createDescription(String i18nKey) { + return new TranslatedDescription(createTranslator(), i18nKey); + } + + protected Translator createTranslator() { + // The user locale is set later, so use the default locale to construct the translator. + return Util.createPackageTranslator(LoginModule.class, Locale.getDefault()); + } +} diff --git a/src/main/java/org/olat/login/validation/ValidationDescription.java b/src/main/java/org/olat/login/validation/ValidationDescription.java new file mode 100644 index 00000000000..7678a31f268 --- /dev/null +++ b/src/main/java/org/olat/login/validation/ValidationDescription.java @@ -0,0 +1,34 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.Locale; + +/** + * + * Initial date: 13 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public interface ValidationDescription { + + public String getText(Locale locale); + +} diff --git a/src/main/java/org/olat/login/validation/ValidationResult.java b/src/main/java/org/olat/login/validation/ValidationResult.java new file mode 100644 index 00000000000..19145a77a66 --- /dev/null +++ b/src/main/java/org/olat/login/validation/ValidationResult.java @@ -0,0 +1,36 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.List; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public interface ValidationResult { + + public boolean isValid(); + + public List<ValidationDescription> getInvalidDescriptions(); + +} diff --git a/src/main/java/org/olat/login/validation/ValidationRule.java b/src/main/java/org/olat/login/validation/ValidationRule.java new file mode 100644 index 00000000000..2089e520135 --- /dev/null +++ b/src/main/java/org/olat/login/validation/ValidationRule.java @@ -0,0 +1,42 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public interface ValidationRule { + + public boolean validate(String value, Identity identity); + + public ValidationDescription getDescription(); + + /** + * + * @return true if a rule uses the identity to validate the password + */ + public boolean isIdentityRule(); + +} diff --git a/src/main/java/org/olat/login/validation/ValidationRulesProvider.java b/src/main/java/org/olat/login/validation/ValidationRulesProvider.java new file mode 100644 index 00000000000..13d9a6013ca --- /dev/null +++ b/src/main/java/org/olat/login/validation/ValidationRulesProvider.java @@ -0,0 +1,34 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.List; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public interface ValidationRulesProvider { + + public List<ValidationRule> getRules(); + +} diff --git a/src/main/java/org/olat/login/validation/ValidationRulesProviderBuilder.java b/src/main/java/org/olat/login/validation/ValidationRulesProviderBuilder.java new file mode 100644 index 00000000000..93664627110 --- /dev/null +++ b/src/main/java/org/olat/login/validation/ValidationRulesProviderBuilder.java @@ -0,0 +1,58 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * Initial date: 19 Jun 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class ValidationRulesProviderBuilder { + + private final List<ValidationRule> rules = new ArrayList<>(); + + public ValidationRulesProviderBuilder add(ValidationRule rule) { + rules.add(rule); + return this; + } + + public ValidationRulesProvider create() { + return new ValidationRulesProviderImpl(rules); + } + + private static class ValidationRulesProviderImpl implements ValidationRulesProvider { + + private final List<ValidationRule> rules; + + private ValidationRulesProviderImpl(List<ValidationRule> rules) { + this.rules = new ArrayList<>(rules); + } + + @Override + public List<ValidationRule> getRules() { + return rules; + } + + } +} diff --git a/src/main/java/org/olat/registration/PwChangeForm.java b/src/main/java/org/olat/registration/PwChangeForm.java index ddde5d35fde..47e9cd57449 100644 --- a/src/main/java/org/olat/registration/PwChangeForm.java +++ b/src/main/java/org/olat/registration/PwChangeForm.java @@ -25,6 +25,8 @@ package org.olat.registration; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import org.olat.basesecurity.BaseSecurity; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -36,8 +38,9 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.core.util.Util; import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.user.ChangePasswordForm; -import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; /** @@ -51,28 +54,26 @@ public class PwChangeForm extends FormBasicController { private TextElement newpass2; // confirm private final TemporaryKey tempKey; - private Identity identityToChange; + private final Identity identityToChange; + private final SyntaxValidator syntaxValidator; @Autowired private RegistrationManager rm; @Autowired - private UserManager userManager; - @Autowired private BaseSecurity securityManager; @Autowired - private OLATAuthManager olatAuthenticationSpi; + private OLATAuthManager olatAuthManager; public PwChangeForm(UserRequest ureq, WindowControl wControl, Identity identityToChange, TemporaryKey tempKey) { super(ureq, wControl, null, Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale())); this.identityToChange = identityToChange; this.tempKey = tempKey; + this.syntaxValidator = olatAuthManager.createPasswordSytaxValidator(); initForm(ureq); } public PwChangeForm(UserRequest ureq, WindowControl wControl, TemporaryKey tempKey) { - super(ureq, wControl, null, Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale())); - this.tempKey = tempKey; - initForm(ureq); + this(ureq, wControl, null, tempKey); } @Override @@ -80,11 +81,11 @@ public class PwChangeForm extends FormBasicController { boolean allOk = super.validateFormLogic(ureq); newpass1.clearError(); - if (!userManager.syntaxCheckOlatPassword(newpass1.getValue())) { - newpass1.setErrorKey("form.checkPassword", null); - allOk &= false; - } else if(!olatAuthenticationSpi.checkCredentialHistory(getIdentityToChange(), newpass1.getValue())) { - newpass1.setErrorKey("form.checkPassword.history", null); + String newPassword = newpass1.getValue(); + ValidationResult validationResult = syntaxValidator.validate(newPassword, getIdentityToChange()); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + newpass1.setErrorKey("error.password.invalid", new String[] { descriptions }); allOk &= false; } @@ -128,15 +129,18 @@ public class PwChangeForm extends FormBasicController { * @param s The identity to change the password. */ private boolean saveFormData(Identity s) { - return olatAuthenticationSpi.changePasswordByPasswordForgottenLink(s, newpass1.getValue()); + return olatAuthManager.changePasswordByPasswordForgottenLink(s, newpass1.getValue()); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { setFormTitle("form.password.enter.new"); - newpass1 = uifactory.addPasswordElement("newpass1", "form.password.new1", 128, "", formLayout); + String descriptions = formatDescriptionAsList(syntaxValidator.getAllDescriptions(), getLocale()); + setFormDescription("form.password.rules", new String[] { descriptions }); + + newpass1 = uifactory.addPasswordElement("newpass1", "form.password.new1", 5000, "", formLayout); newpass1.setAutocomplete("new-password"); - newpass2 = uifactory.addPasswordElement("newpass2", "form.password.new2", 128, "", formLayout); + newpass2 = uifactory.addPasswordElement("newpass2", "form.password.new2", 5000, "", formLayout); newpass2.setAutocomplete("new-password"); uifactory.addFormSubmitButton("submit", formLayout); } diff --git a/src/main/java/org/olat/registration/RegistrationForm2.java b/src/main/java/org/olat/registration/RegistrationForm2.java index 70c8dbff7d8..3ba3e7604c2 100644 --- a/src/main/java/org/olat/registration/RegistrationForm2.java +++ b/src/main/java/org/olat/registration/RegistrationForm2.java @@ -25,11 +25,12 @@ package org.olat.registration; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import java.util.HashMap; import java.util.List; import java.util.Map; -import org.olat.basesecurity.BaseSecurity; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -46,9 +47,11 @@ import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.i18n.I18nManager; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.olat.user.ChangePasswordForm; import org.olat.user.UserManager; -import org.olat.user.UserModule; import org.olat.user.propertyhandlers.UserPropertyHandler; import org.springframework.beans.factory.annotation.Autowired; @@ -65,7 +68,7 @@ public class RegistrationForm2 extends FormBasicController { private final Map<String,FormItem> propFormItems = new HashMap<>(); private SingleSelection lang; - private TextElement username; + private TextElement usernameEl; private StaticTextElement usernameStatic; private TextElement newpass1; private TextElement newpass2; // confirm @@ -73,28 +76,24 @@ public class RegistrationForm2 extends FormBasicController { private final String proposedUsername; private final boolean userInUse; private final boolean usernameReadonly; + private final SyntaxValidator passwordSyntaxValidator; + private final SyntaxValidator usernameSyntaxValidator; - @Autowired - private UserModule userModule; @Autowired private I18nManager i18nManager; @Autowired private UserManager userManager; @Autowired - private BaseSecurity securityManager; + private OLATAuthManager olatAuthManager; - /** - * @param name - * @param languageKey - */ - public RegistrationForm2(UserRequest ureq, WindowControl wControl, String languageKey, String proposedUsername, boolean userInUse, boolean usernameReadonly) { super(ureq, wControl, null, Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale())); - this.languageKey = languageKey; this.proposedUsername = proposedUsername; this.userInUse = userInUse; this.usernameReadonly = usernameReadonly; + this.passwordSyntaxValidator = olatAuthManager.createPasswordSytaxValidator(); + this.usernameSyntaxValidator = olatAuthManager.createUsernameSytaxValidator(); initForm(ureq); } @@ -121,23 +120,25 @@ public class RegistrationForm2 extends FormBasicController { } protected String getLogin() { - if(username != null) { - return username.getValue().trim(); + if(usernameEl != null) { + return usernameEl.getValue().trim(); } else if (usernameStatic != null) { return usernameStatic.getValue().trim(); } return null; } + private void setLogin(String login) { - if(username != null) { - username.setValue(login); + if(usernameEl != null) { + usernameEl.setValue(login); } else if (usernameStatic != null) { usernameStatic.setValue(login); } } + private void setLoginErrorKey(String errorKey) { - if(username != null) { - username.setErrorKey(errorKey, new String[0]); + if(usernameEl != null) { + usernameEl.setErrorKey(errorKey, new String[0]); } else if (usernameStatic != null) { usernameStatic.setErrorKey(errorKey, new String[0]); } @@ -146,12 +147,10 @@ public class RegistrationForm2 extends FormBasicController { protected String getPassword() { return newpass1.getValue().trim(); } + protected FormItem getPropFormItem(String k) { return propFormItems.get(k); } - /** - * Initialize the form - */ @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { @@ -184,8 +183,8 @@ public class RegistrationForm2 extends FormBasicController { if(usernameReadonly) { usernameStatic = uifactory.addStaticTextElement("username", "user.login", proposedUsername, formLayout); } else { - username = uifactory.addTextElement("username", "user.login", 128, "", formLayout); - username.setMandatory(true); + usernameEl = uifactory.addTextElement("username", "user.login", 128, "", formLayout); + usernameEl.setMandatory(true); } if(proposedUsername != null) { @@ -195,10 +194,13 @@ public class RegistrationForm2 extends FormBasicController { setLoginErrorKey("form.check6"); } - newpass1 = uifactory.addPasswordElement("newpass1", "form.password.new1", 128, "", formLayout); + String descriptions = formatDescriptionAsList(passwordSyntaxValidator.getAllDescriptions(), getLocale()); + uifactory.addStaticTextElement("form.password.rules", null, + translate("form.password.rules", new String[] { descriptions }), formLayout); + newpass1 = uifactory.addPasswordElement("newpass1", "form.password.new1", 5000, "", formLayout); newpass1.setMandatory(true); newpass1.setAutocomplete("new-password"); - newpass2 = uifactory.addPasswordElement("newpass2", "form.password.new2", 128, "", formLayout); + newpass2 = uifactory.addPasswordElement("newpass2", "form.password.new2", 5000, "", formLayout); newpass2.setMandatory(true); newpass2.setAutocomplete("new-password"); @@ -212,45 +214,57 @@ public class RegistrationForm2 extends FormBasicController { @Override protected boolean validateFormLogic (UserRequest ureq) { + boolean allOk = true; + // validate each user field for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { FormItem fi = propFormItems.get(userPropertyHandler.getName()); if (!userPropertyHandler.isValid(null, fi, null)) { - return false; + allOk &= false; } } - if (!UserManager.getInstance().syntaxCheckOlatLogin(getLogin())) { - setLoginErrorKey("form.check3"); - return false; - } + // Transient identity for validations + Identity newIdentity = getIdentity(); - Identity s = securityManager.findIdentityByName(getLogin()); - if (s != null || userModule.isLoginOnBlacklist(getLogin())) { - setLoginErrorKey("form.check6"); - return false; + // validate if username does match the syntactical login requirements + usernameEl.clearError(); + String username = usernameEl.getValue(); + if (!StringHelper.containsNonWhitespace(username)) { + usernameEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else { + ValidationResult validationResult = usernameSyntaxValidator.validate(username, newIdentity); + if (!validationResult.isValid()) { + String descriptions = validationResult.getInvalidDescriptions().get(0).getText(getLocale()); + usernameEl.setErrorKey("error.username.invalid", new String[] { descriptions }); + allOk &= false; + } } if (newpass1.getValue().equals("")) { newpass1.setErrorKey("form.check4", null); - return false; + allOk &= false; } if (newpass2.getValue().equals("")) { newpass2.setErrorKey("form.check4", null); - return false; + allOk &= false; } - if (!UserManager.getInstance().syntaxCheckOlatPassword(newpass1.getValue())) { - newpass1.setErrorKey("form.checkPassword", null); - return false; - } + String newPassword = newpass1.getValue(); + ValidationResult validationResult = passwordSyntaxValidator.validate(newPassword, newIdentity); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + newpass1.setErrorKey("error.password.invalid", new String[] { descriptions }); + allOk &= false; + } if (!newpass1.getValue().equals(newpass2.getValue())) { newpass2.setErrorKey("form.check5", null); - // OO-92 : must return false, if passwords don't match! - return false; + allOk &= false; } - return true; + + return allOk & super.validateFormLogic(ureq); } @Override diff --git a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties index 2b1855f7a89..b480cd44f7f 100644 --- a/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_de.properties @@ -58,6 +58,7 @@ form.password.enter.new=Passwort neu setzen form.password.error.nomatch=Beide Passw\u00F6rter m\u00FCssen gleich sein form.password.new1=Neues Passwort form.password.new2=Passwort best\u00E4tigen +form.password.rules=$org.olat.user\:form.password.validation.rules login.body=Sie sind bereits in OpenOLAT registriert unter dem Benutzernamen\: {0} \n\nFalls Sie diese E-Mail unaufgefordert erhalten haben, l\u00F6schen Sie ganz einfach diese E-Mail.\n\nIhr OpenOLAT-Team \n login.subject=Bereits vorhandene Registrierung in OpenOLAT loginhelp=Der Benutzername<ul><li>muss mindestens 4 Zeichen lang sein</li><li>darf nur Ziffern und / oder Kleinbuchstaben enthalten (keine Umlaute, keine Sonderzeichen ausser .-_)</li><li>kann sp\u00E4ter nicht mehr ge\u00E4ndert werden</li></ul> @@ -72,7 +73,7 @@ pw.change.sms=SMS Authentifizierung starten pw.change.sms.descr=Sie haben eine Mobile Telefonnummer in OpenOLAT hinterlegt. Sie k\u00F6nnen sich daher \u00FCber SMS authentifizieren. W\u00E4hlen Sie den untenstehenden Button, um die SMS-Authentifizierung zu starten\: pw.change.sms.title=SMS Authentifizierung pwchange.headline=<p><b>Schl\u00FCssel f\u00FCr neues OpenOLAT-Passwort</b></p> -pwchange.body=<p>Klicken Sie <a href='{0}/dmz/pwchange/index.html?key\={1}&language\={2}'>hier um Ihr OpenOLAT Passwort neu zu setzen</a>. \nAnschließend k\u00F6nnen Sie sich bei <a href='{0}/dmz/1%3A1%3Aomain_loging%3A1%3A0%3Acid%3Alogin/?lp\=OLAT'>OpenOLAT anmelden</a>.</p> +pwchange.body=<p>Klicken Sie <a href='{0}/dmz/pwchange/index.html?key\={1}&language\={2}'>hier um Ihr OpenOLAT Passwort neu zu setzen</a>. \nAnschlie\uFFFDend k\u00F6nnen Sie sich bei <a href='{0}/dmz/1%3A1%3Aomain_loging%3A1%3A0%3Acid%3Alogin/?lp\=OLAT'>OpenOLAT anmelden</a>.</p> pwchange.body.alt=<p>Falls Ihr Emailprogramm HTML nicht unterst\u00FCtzt, kopieren Sie den folgenden Link in Ihren Webbrowser: </br><a href='{0}/dmz/pwchange/index.html?key\={1}&language\={2}'>{0}/dmz/pwchange/index.html?key\={1}&language\={2}</a><p> pwchange.homelink=Klicken Sie hier um sich anzumelden pwchange.intro=Sie oder eine andere Person haben f\u00FCr den OpenOLAT-Benutzeraccount {0} ein neues Passwort angefordert.\n\n diff --git a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties index d16e9d82795..03acdab8a47 100644 --- a/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/registration/_i18n/LocalStrings_en.properties @@ -58,6 +58,7 @@ form.password.enter.new=Set new password form.password.error.nomatch=Passwords do not match. form.password.new1=New password form.password.new2=Confirm password +form.password.rules=$org.olat.user\:form.password.validation.rules login.body=You are already registered in OpenOLAT. Your user name is\: {0}.\n\nIn case you got this e-mail unwanted, please delete it.\n\nYour OpenOLAT team.\n login.subject=You are already registered in OpenOLAT. loginhelp=A user name<ul><li>must contain at least 4 characters</li><li>may only contain digits and/or lower case letters (no special digits or umlauts except for . - _)</li><li>cannot be changed later on</li></ul> diff --git a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java index cee7eed5746..a6edf76b314 100644 --- a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java +++ b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationController.java @@ -262,7 +262,7 @@ public class ShibbolethRegistrationController extends DefaultController implemen } } else if (source == regForm) { if (event == Event.DONE_EVENT) { - String choosenLogin = regForm.getLogin(); + String choosenLogin = regForm.getUsernameEl(); Identity identity = securityManager.findIdentityByName(choosenLogin); @@ -304,7 +304,7 @@ public class ShibbolethRegistrationController extends DefaultController implemen if(regForm == null ) { choosenLogin = proposedUsername; } else { - choosenLogin = regForm.getLogin(); + choosenLogin = regForm.getUsernameEl(); } // check if login has been taken by another user in the meantime... diff --git a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationForm.java b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationForm.java index 7a5ed0b8b9a..626f6138bfd 100644 --- a/src/main/java/org/olat/shibboleth/ShibbolethRegistrationForm.java +++ b/src/main/java/org/olat/shibboleth/ShibbolethRegistrationForm.java @@ -25,6 +25,7 @@ package org.olat.shibboleth; +import org.olat.admin.user.imp.TransientIdentity; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.TextElement; @@ -32,8 +33,12 @@ import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; -import org.olat.user.UserManager; -import org.olat.user.UserModule; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; +import org.olat.user.ChangePasswordForm; import org.springframework.beans.factory.annotation.Autowired; /** @@ -47,42 +52,48 @@ import org.springframework.beans.factory.annotation.Autowired; public class ShibbolethRegistrationForm extends FormBasicController { - private TextElement login; + private TextElement usernameEl; private String proposedUsername; - - @Autowired - private UserModule userModule; + + private final SyntaxValidator usernameSyntaxValidator; + @Autowired - private UserManager userManager; - /** - * @param name - * @param translator - */ + private OLATAuthManager olatAuthManager; public ShibbolethRegistrationForm(UserRequest ureq, WindowControl wControl, String proposedUsername) { super(ureq, wControl); + setTranslator(Util.createPackageTranslator(ChangePasswordForm.class, ureq.getLocale(), getTranslator())); this.proposedUsername = proposedUsername; + this.usernameSyntaxValidator = olatAuthManager.createUsernameSytaxValidator(); initForm(ureq); } @Override protected boolean validateFormLogic(UserRequest ureq) { - if (login.isEmpty("srf.error.loginempty")) return false; - if (!userManager.syntaxCheckOlatLogin(getLogin())) { - login.setErrorKey("srf.error.loginregexp", null); + // validate if username does match the syntactical login requirements + usernameEl.clearError(); + String username = usernameEl.getValue(); + if (!StringHelper.containsNonWhitespace(username)) { + usernameEl.setErrorKey("form.legende.mandatory", null); return false; - } - if (userModule.isLoginOnBlacklist(getLogin())) { - login.setErrorKey("srf.error.blacklist", null); + } + + TransientIdentity newIdentity = new TransientIdentity(); + newIdentity.setName(username); + ValidationResult validationResult = usernameSyntaxValidator.validate(username, newIdentity); + if (!validationResult.isValid()) { + String descriptions = validationResult.getInvalidDescriptions().get(0).getText(getLocale()); + usernameEl.setErrorKey("error.username.invalid", new String[] { descriptions }); return false; } + return true; } /** * @return Login field. */ - protected String getLogin() { return login.getValue(); } + protected String getUsernameEl() { return usernameEl.getValue(); } @Override protected void formOK(UserRequest ureq) { @@ -92,8 +103,8 @@ public class ShibbolethRegistrationForm extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { String initialValue = proposedUsername == null ? "" : proposedUsername; - login = uifactory.addTextElement("srf_login", "srf.login", 128, initialValue, formLayout); - login.setExampleKey("srf.login.example", null); + usernameEl = uifactory.addTextElement("srf_login", "srf.login", 128, initialValue, formLayout); + usernameEl.setExampleKey("srf.login.example", null); uifactory.addFormSubmitButton("save", formLayout); } diff --git a/src/main/java/org/olat/user/ChangePasswordController.java b/src/main/java/org/olat/user/ChangePasswordController.java index 685c21378d5..dab7105d027 100644 --- a/src/main/java/org/olat/user/ChangePasswordController.java +++ b/src/main/java/org/olat/user/ChangePasswordController.java @@ -87,10 +87,6 @@ public class ChangePasswordController extends BasicController implements Support @Autowired private OLATAuthManager olatAuthenticationSpi; - /** - * @param ureq - * @param wControl - */ public ChangePasswordController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl); diff --git a/src/main/java/org/olat/user/ChangePasswordForm.java b/src/main/java/org/olat/user/ChangePasswordForm.java index 10c9f038a62..9ac8b37cfe2 100644 --- a/src/main/java/org/olat/user/ChangePasswordForm.java +++ b/src/main/java/org/olat/user/ChangePasswordForm.java @@ -25,6 +25,8 @@ package org.olat.user; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.TextElement; @@ -35,6 +37,8 @@ import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.springframework.beans.factory.annotation.Autowired; @@ -56,51 +60,55 @@ public class ChangePasswordForm extends FormBasicController { private String oldCred = ""; private String newCred = ""; + private final SyntaxValidator syntaxValidator; private final Identity identityToChange; @Autowired - private UserManager userManager; - @Autowired - private OLATAuthManager olatAuthenticationSpi; + private OLATAuthManager olatAuthManager; - /** - * @param name - */ public ChangePasswordForm(UserRequest ureq, WindowControl wControl, Identity identityToChange) { super(ureq, wControl); this.identityToChange = identityToChange; + this.syntaxValidator = olatAuthManager.createPasswordSytaxValidator(); initForm(ureq); } - /** - * @return Old password field value. - */ public String getOldPasswordValue() { return oldCred; } - /** - * @return New password field value. - */ public String getNewPasswordValue() { return newCred; } @Override - protected void formOK(UserRequest ureq) { - oldCred = oldCredEl.getValue(); - newCred = newCredEl.getValue(); + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String descriptions = formatDescriptionAsList(syntaxValidator.getAllDescriptions(), getLocale()); + setFormDescription("form.password.validation.rules", new String[] { descriptions }); - oldCredEl.setValue(""); - newCredEl.setValue(""); - newCredConfirmationEl.setValue(""); + oldCredEl = uifactory.addPasswordElement("oldpass", "form.password.old", 5000, "", formLayout); + oldCredEl.setElementCssClass("o_sel_home_pwd_old"); + oldCredEl.setNotEmptyCheck("form.please.enter.old"); + oldCredEl.setMandatory(true); - fireEvent (ureq, Event.DONE_EVENT); - } - - @Override - protected void formCancelled(UserRequest ureq) { - fireEvent (ureq, Event.CANCELLED_EVENT); + newCredEl = uifactory.addPasswordElement("newpass1", "form.password.new1", 5000, "", formLayout); + newCredEl.setNotEmptyCheck("form.please.enter.new"); + newCredEl.setElementCssClass("o_sel_home_pwd_new_1"); + newCredEl.setAutocomplete("new-password"); + newCredEl.setMandatory(true); + + newCredConfirmationEl = uifactory.addPasswordElement("newpass2", "form.password.new2", 5000, "", formLayout); + newCredConfirmationEl.setNotEmptyCheck("form.please.enter.new"); + newCredConfirmationEl.setElementCssClass("o_sel_home_pwd_new_2"); + newCredConfirmationEl.setAutocomplete("new-password"); + newCredConfirmationEl.setMandatory(true); + + // Button layout + FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); + buttonLayout.setElementCssClass("o_sel_home_pwd_buttons"); + formLayout.add(buttonLayout); + uifactory.addFormSubmitButton("submit", buttonLayout); + uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); } @Override @@ -108,18 +116,16 @@ public class ChangePasswordForm extends FormBasicController { boolean allOk = super.validateFormLogic(ureq); newCredEl.clearError(); - if (!userManager.syntaxCheckOlatPassword(newCredEl.getValue())) { - newCredEl.setErrorKey("form.checkPassword", null); - allOk &= false; - } else if(!olatAuthenticationSpi.checkCredentialHistory(identityToChange, newCredEl.getValue())) { - newCredEl.setErrorKey("form.checkPassword.history", null); + String newPassword = newCredEl.getValue(); + ValidationResult validationResult = syntaxValidator.validate(newPassword, identityToChange); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + newCredEl.setErrorKey("error.password.invalid", new String[] { descriptions }); allOk &= false; } newCredConfirmationEl.clearError(); if (!newCredEl.getValue().equals(newCredConfirmationEl.getValue())) { - newCredEl.setValue(""); - newCredConfirmationEl.setValue(""); newCredConfirmationEl.setErrorKey("error.password.nomatch", null); allOk &= false; } @@ -128,30 +134,20 @@ public class ChangePasswordForm extends FormBasicController { } @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - oldCredEl = uifactory.addPasswordElement("oldpass", "form.password.old", 128, "", formLayout); - oldCredEl.setElementCssClass("o_sel_home_pwd_old"); - oldCredEl.setNotEmptyCheck("form.please.enter.old"); - oldCredEl.setMandatory(true); - - newCredEl = uifactory.addPasswordElement("newpass1", "form.password.new1", 128, "", formLayout); - newCredEl.setNotEmptyCheck("form.please.enter.new"); - newCredEl.setElementCssClass("o_sel_home_pwd_new_1"); - newCredEl.setAutocomplete("new-password"); - newCredEl.setMandatory(true); + protected void formOK(UserRequest ureq) { + oldCred = oldCredEl.getValue(); + newCred = newCredEl.getValue(); - newCredConfirmationEl = uifactory.addPasswordElement("newpass2", "form.password.new2", 128, "", formLayout); - newCredConfirmationEl.setNotEmptyCheck("form.please.enter.new"); - newCredConfirmationEl.setElementCssClass("o_sel_home_pwd_new_2"); - newCredConfirmationEl.setAutocomplete("new-password"); - newCredConfirmationEl.setMandatory(true); + oldCredEl.setValue(""); + newCredEl.setValue(""); + newCredConfirmationEl.setValue(""); - // Button layout - FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); - buttonLayout.setElementCssClass("o_sel_home_pwd_buttons"); - formLayout.add(buttonLayout); - uifactory.addFormSubmitButton("submit", buttonLayout); - uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent (ureq, Event.CANCELLED_EVENT); } @Override diff --git a/src/main/java/org/olat/user/UserManager.java b/src/main/java/org/olat/user/UserManager.java index 0cef00a5a73..b886d260e36 100644 --- a/src/main/java/org/olat/user/UserManager.java +++ b/src/main/java/org/olat/user/UserManager.java @@ -54,7 +54,6 @@ public abstract class UserManager { // injected by spring configuration protected UserPropertiesConfig userPropertiesConfig; - protected UserNameAndPasswordSyntaxChecker userNameAndPasswordSyntaxChecker; /** * Use getInstance method @@ -197,26 +196,6 @@ public abstract class UserManager { */ public abstract String getUserCharset(Identity identity); - /** - * Validates an OLAT password on a syntactical level. - * - * @param password The passwort to validate - * @return true if it is valid, false otherwhise - */ - public boolean syntaxCheckOlatPassword(String password) { - return userNameAndPasswordSyntaxChecker.syntaxCheckOlatPassword(password); - } - - /** - * Check if the login matches. - * - * @param login - * @return True if synatx is ok. - */ - public boolean syntaxCheckOlatLogin(String login) { - return userNameAndPasswordSyntaxChecker.syntaxCheckOlatLogin(login); - } - public UserPropertiesConfig getUserPropertiesConfig() { return userPropertiesConfig; } @@ -245,14 +224,6 @@ public abstract class UserManager { return userPropertiesConfig.isUserViewReadOnly(usageIdentifyer, propertyHandler); } - /** - * Spring setter - * @param userNameAndPasswordSyntaxChecker - */ - public void setUserNameAndPasswordSyntaxChecker(UserNameAndPasswordSyntaxChecker userNameAndPasswordSyntaxChecker) { - this.userNameAndPasswordSyntaxChecker = userNameAndPasswordSyntaxChecker; - } - /** * Spring setter * @param userPropertiesConfig diff --git a/src/main/java/org/olat/user/UserNameAndPasswordSyntaxChecker.java b/src/main/java/org/olat/user/UserNameAndPasswordSyntaxChecker.java deleted file mode 100644 index 204e8c3fbb1..00000000000 --- a/src/main/java/org/olat/user/UserNameAndPasswordSyntaxChecker.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.user; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * <h3>Description:</h3> - * This login name and password syntax checker provides methods to check if a - * user name and a password is syntactically correct. Inherit from this class - * and configure your own checker in the spring user manager configuration to - * allow different user names that the default (e.g. if you want to use email - * addresses as login names) - * <p> - * Initial Date: 31.07.2007 <br> - * - * @author Florian Gnaegi, frentix GmbH, http://www.frentix.com - */ -public class UserNameAndPasswordSyntaxChecker { - - /** - * Validates an OLAT password on a syntactical level. A password is valid when - * it matches the following requrements:<br> - * <ol> - * <li />Only numbers (0-9), letters (a-z, A-Z) and the following special - * characters (!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~) are allowed - * <li />Size is between 4 and 128 characters - * <li />At least one number and at least one letter must be used - * </ol> - * - * @param password The passwort to validate - * @return true if it is valid, false otherwhise - */ - public boolean syntaxCheckOlatPassword(String password) { - Pattern p = Pattern.compile("^\\p{Graph}{4,128}$"); - Matcher m = p.matcher(password); - - if (m.matches()) { - if (!password.matches(".*['\"]+.*")) { - if (password.matches(".*\\p{Alpha}+.*")) { - if (password.matches(".*\\p{Digit}+.*")) return true; - } - } - } - return false; - } - - /** - * Checks for a valid login name. The method does only check if the name is - * syntactically correct. It does not check if the name is valid - * - * @param login - * @return True if synatx is ok. - */ - public boolean syntaxCheckOlatLogin(String login) { - // Allow only alphanumeric login names - must be like this to generate - // valid jabber user ID's. No support for generic UTF-8 login names... - //if you want to user email adresses as login names check the instant messaging config as you have to replace the @ for jabber names - return login.matches("[0-9a-z\\.\\-_]{3,64}"); - } - -} diff --git a/src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithEmail.java b/src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithEmail.java deleted file mode 100644 index 97f34af1e9f..00000000000 --- a/src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithEmail.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.user; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * <h3>Description:</h3> - * This login name and password syntax checker provides methods to check if a - * user name and a password is syntactically correct. Inherit from this class - * and configure your own checker in the spring user manager configuration to - * allow different user names that the default (e.g. if you want to use email - * addresses as login names) - * <p> - * Initial Date: 5.06.2008 <br> - * - * @author Roman Haag, frentix GmbH, http://www.frentix.com - */ -public class UserNameAndPasswordSyntaxCheckerWithEmail extends UserNameAndPasswordSyntaxChecker { - - /** - * Validates an OLAT password on a syntactical level. A password is valid when - * it matches the following requrements:<br> - * <ol> - * <li />Only numbers (0-9), letters (a-z, A-Z) and the following special - * characters (!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~) are allowed - * <li />Size is between 4 and 128 characters - * <li />At least one number and at least one letter must be used - * </ol> - * - * @param password The passwort to validate - * @return true if it is valid, false otherwhise - */ - @Override - public boolean syntaxCheckOlatPassword(String password) { - Pattern p = Pattern.compile("^\\p{Graph}{4,128}$"); - Matcher m = p.matcher(password); - - if (m.matches()) { - if (!password.matches(".*['\"]+.*")) { - if (password.matches(".*\\p{Alpha}+.*")) { - if (password.matches(".*\\p{Digit}+.*")) return true; - } - } - } - return false; - } - - /** - * Checks for a valid login name. The method does only check if the name is - * syntactically correct. It does not check if the name is valid - * - * @param login - * @return True if syntax is ok. - */ - @Override - public boolean syntaxCheckOlatLogin(String login) { - // Allow only alphanumeric login names - // @ is allowed also (will be replaced for Jabber) - return login.matches("[0-9a-z\\.\\-_]{4,64}") || login.matches("[0-9a-z\\.\\-_@]{6,64}"); - } - -} diff --git a/src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexp.java b/src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexp.java deleted file mode 100644 index 1c0fe240b9f..00000000000 --- a/src/main/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexp.java +++ /dev/null @@ -1,102 +0,0 @@ -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ -package org.olat.user; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import org.apache.logging.log4j.Logger; -import org.olat.core.logging.Tracing; - -/** - * Description:<br> - * This configurable password and syntax checker can be used if you need a - * custom loginname / password rule. Don't forget to adapt the corresponding - * i18n keys. - * - * <P> - * Initial Date: 15.12.2008 <br> - * - * @author gnaegi - */ -public class UserNameAndPasswordSyntaxCheckerWithRegexp extends UserNameAndPasswordSyntaxChecker { - private static final Logger log = Tracing.createLoggerFor(UserNameAndPasswordSyntaxCheckerWithEmail.class); - // precompiled patterns with default values - private Pattern passwordPattern = Pattern.compile("^\\p{Graph}{4,128}$"); - private Pattern usernamePattern = Pattern.compile("[0-9a-z\\.\\-_@]{3,32}"); - - /** - * Validates an OLAT password on a syntactical level. A password is valid when - * it matches the requirements that are set in the spring configuration. - * <p> - * - * @param password The passwort to validate - * @return true if it is valid, false otherwhise - */ - @Override - public boolean syntaxCheckOlatPassword(String password) { - Matcher m = passwordPattern.matcher(password); - return m.matches(); - } - - /** - * Checks for a valid user name. The method does only check if the name is - * syntactically correct. It does not check if the name is valid (already in - * use by another user) - * - * @param login - * @return True if syntax is ok. - */ - @Override - public boolean syntaxCheckOlatLogin(String login) { - Matcher m = usernamePattern.matcher(login); - return m.matches(); - } - - /** - * Spring setter to set new password regular expression - * @param passwordRegExp - */ - public void setPasswordRegExp(String passwordRegExp) { - try { - passwordPattern = Pattern.compile(passwordRegExp); - } catch (PatternSyntaxException e) { - log.error("Invalid regular expression::" + passwordRegExp + " for password checker", e); - } - } - - /** - * Spring setter to set new useranem regular expression - * @param usernameRegExp - */ - public void setUsernameRegExp(String usernameRegExp) { - try { - usernamePattern = Pattern.compile(usernameRegExp); - } catch (PatternSyntaxException e) { - log.error("Invalid regular expression::" + usernameRegExp + " for username checker", e); - } - } -} diff --git a/src/main/java/org/olat/user/WebDAVPasswordController.java b/src/main/java/org/olat/user/WebDAVPasswordController.java index 89fab88f9dd..4a0e0cefb47 100644 --- a/src/main/java/org/olat/user/WebDAVPasswordController.java +++ b/src/main/java/org/olat/user/WebDAVPasswordController.java @@ -20,6 +20,8 @@ package org.olat.user; +import static org.olat.login.ui.LoginUIFactory.formatDescriptionAsList; + import java.util.List; import org.olat.basesecurity.Authentication; @@ -44,6 +46,9 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; +import org.olat.login.auth.OLATAuthManager; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationResult; import org.springframework.beans.factory.annotation.Autowired; /** @@ -60,6 +65,7 @@ public class WebDAVPasswordController extends FormBasicController { private FormSubmit saveButton; private FormCancel cancelButton; private FormLink newButton; + private StaticTextElement rulesEl; private TextElement passwordEl; private TextElement confirmPasswordEl; private StaticTextElement usernamesStaticEl; @@ -67,15 +73,20 @@ public class WebDAVPasswordController extends FormBasicController { private FormLayoutContainer accessDataFlc; private FormLayoutContainer buttonGroupLayout; + private final SyntaxValidator syntaxValidator; + @Autowired private UserModule userModule; @Autowired private BaseSecurity securityManager; @Autowired + private OLATAuthManager olatAuthManager; + @Autowired private WebDAVAuthManager webDAVAuthManager; public WebDAVPasswordController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl, "pwdav", Util.createPackageTranslator(FolderRunController.class, ureq.getLocale())); + this.syntaxValidator = olatAuthManager.createPasswordSytaxValidator(); initForm(ureq); } @@ -118,10 +129,15 @@ public class WebDAVPasswordController extends FormBasicController { String passwordPlaceholder = getTranslator().translate(passwordPlaceholderKey); passwordStaticEl = uifactory.addStaticTextElement("pwdav.password", "pwdav.password", passwordPlaceholder, accessDataFlc); - passwordEl = uifactory.addPasswordElement("pwdav.password.2", "pwdav.password", 64, "", accessDataFlc); + String descriptions = formatDescriptionAsList(syntaxValidator.getAllDescriptions(), getLocale()); + rulesEl = uifactory.addStaticTextElement("pwdav.password.rules", null, + translate("pwdav.password.rules", new String[] { descriptions }), accessDataFlc); + rulesEl.setVisible(false); + + passwordEl = uifactory.addPasswordElement("pwdav.password.2", "pwdav.password", 5000, "", accessDataFlc); passwordEl.setVisible(false); passwordEl.setMandatory(true); - confirmPasswordEl = uifactory.addPasswordElement("pwdav.password.confirm", "pwdav.password.confirm", 64, "", accessDataFlc); + confirmPasswordEl = uifactory.addPasswordElement("pwdav.password.confirm", "pwdav.password.confirm", 5000, "", accessDataFlc); confirmPasswordEl.setVisible(false); confirmPasswordEl.setMandatory(true); @@ -170,7 +186,7 @@ public class WebDAVPasswordController extends FormBasicController { } } - return sb.toString(); + return sb.toString(); } @Override @@ -182,16 +198,13 @@ public class WebDAVPasswordController extends FormBasicController { protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = true; if(passwordEl.isVisible()) { + passwordEl.clearError(); String password = passwordEl.getValue(); - boolean valid = UserManager.getInstance().syntaxCheckOlatPassword(passwordEl.getValue()); - if(StringHelper.containsNonWhitespace(password) && valid) { - passwordEl.clearError(); - } else if (!valid){ - passwordEl.setErrorKey("form.checkPassword", null); - allOk = false; - } else { - passwordEl.setErrorKey("error.password.empty", null); - allOk = false; + ValidationResult validationResult = syntaxValidator.validate(password, getIdentity()); + if (!validationResult.isValid()) { + String descriptions = formatDescriptionAsList(validationResult.getInvalidDescriptions(), getLocale()); + passwordEl.setErrorKey("error.password.invalid", new String[] { descriptions }); + allOk &= false; } String confirmation = confirmPasswordEl.getValue(); @@ -234,6 +247,7 @@ public class WebDAVPasswordController extends FormBasicController { passwordStaticEl.setVisible(!visible); saveButton.setVisible(visible); cancelButton.setVisible(visible); + rulesEl.setVisible(visible); passwordEl.setVisible(visible); confirmPasswordEl.setVisible(visible); diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_ar.properties index 8a4d38f35b1..7e7812d100a 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_ar.properties @@ -25,8 +25,6 @@ error.password.noauth=\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0 error.password.nomatch=\u0644\u0627 \u064A\u0648\u062C\u062F \u062A\u0637\u0627\u0628\u0642 \u0628\u064A\u0646 \u0643\u0644\u0645\u062A\u0627\u0646 \u0627\u0644\u0645\u0631\u0648\u0631 \u0627\u0644\u062C\u062F\u064A\u062F\u062A\u0627\u0646. form.address=\u0627\u0644\u0639\u0646\u0648\u0627\u0646 form.charset=\u0645\u062C\u0645\u0648\u0639\u0629 \u0631\u0645\u0648\u0632 \u062A\u0633\u062A\u062E\u062F\u0645 \u0641\u0649 \u0627\u0644\u062A\u0646\u0632\u064A\u0644 -form.checkPassword=\u0643\u0644\u0645\u0629 \u0627\u0644\u0645\u0631\u0648\u0631 \u0627\u0644\u062E\u0627\u0635\u0629 \u0628\u0643 \u064A\u062C\u0628 \u0623\u0646 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0645\u0627 \u0644\u0627 \u064A\u0642\u0644 \u0639\u0646 4 \u062D\u0631\u0648\u0641 \u0648\u062A\u0634\u0645\u0644 \u0627\u0644\u0623\u0631\u0642\u0627\u0645 \u0648\u0627\u0644\u062D\u0631\u0648\u0641.. -form.checkUsername=\u0623\u0633\u0645\u0627\u0621 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\u064A\u0646 \u064A\u062C\u0628 \u0623\u0646 \u062A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0645\u0627 \u0644\u0627 \u064A\u0642\u0644 \u0639\u0646 4 \u0623\u062D\u0631\u0641 \u0648 \u0627\u0644\u062D\u0631\u0648\u0641 \u0641\u0642\u0637 \u0645\u0646 \u0627\u0644\u0623\u0644\u0641 \u0625\u0644\u0649 \u0627\u0644\u064A\u0627\u0621\u060C \u0641\u0636\u0644\u0627 \u0639\u0646 \u0627\u0644\u0623\u0631\u0642\u0627\u0645 \u0645\u0646 0 \u0625\u0644\u0649 9\u060C \u0648\u0628\u0627\u0644\u0625\u0636\u0627\u0641\u0629 \u0625\u0644\u0649 \u0630\u0644\u0643\u060C \u064A\u062C\u0648\u0632 \u0644\u0643 \u0627\u0633\u062A\u062E\u062F\u0627\u0645. _ \u0648-. form.description=\u064A\u0631\u062C\u0649 \u0643\u062A\u0627\u0628\u0629 \u0628\u064A\u0627\u0646\u0627\u062A\u0643 \u0627\u0644\u0634\u062E\u0635\u064A\u0629 \u0641\u0649 \u0647\u0630\u0627 \u0627\u0644\u0646\u0645\u0648\u0630\u062C\u060C \u0648\u0639\u0646 \u0637\u0631\u064A\u0642 \u0645\u0631\u0628\u0639\u0627\u062A \u0627\u0644\u0627\u062E\u062A\u064A\u0627\u0631 \u064A\u0645\u0643\u0646\u0643 \u062A\u062D\u062F\u064A\u062F \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u062A\u0649 \u062A\u0631\u064A\u062F \u0623\u0646 \u062A\u0638\u0647\u0631 \u0641\u0649 \u0628\u0637\u0627\u0642\u0629 \u0627\u0644\u062A\u0639\u0627\u0631\u0641 \u0627\u0644\u062E\u0627\u0635\u0629 \u0628\u0643. form.email=\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0627\u0644\u0643\u062A\u0631\u0648\u0646\u0649 form.fields=\u0627\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062A diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_bg.properties index 708d4fcef48..2c75c8c2ca3 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_bg.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_bg.properties @@ -25,8 +25,7 @@ error.password.noauth=\u041F\u0440\u0435\u0434\u0438\u0448\u043D\u0430\u0442\u04 error.password.nomatch=\u0414\u0432\u0435\u0442\u0435 \u043D\u043E\u0432\u0438 \u043F\u0430\u0440\u043E\u043B\u0438 \u043D\u0435 \u0441\u044A\u0432\u043F\u0430\u0434\u0430\u0442. form.address=\u0410\u0434\u0440\u0435\u0441 form.charset=\u0417\u043D\u0430\u043A\u043E\u0433\u0435\u043D\u0435\u0440\u0430\u0442\u043E\u0440 \u0438\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u043D \u043F\u0440\u0438 \u0438\u0437\u0442\u0435\u0433\u043B\u044F\u043D\u0435 -form.checkPassword=\u0412\u0430\u0448\u0430\u0442\u0430 \u043F\u0430\u0440\u043E\u043B\u0430 \u0442\u0440\u044F\u0431\u0432\u0430 \u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430 \u043F\u043E\u043D\u0435 4 \u0437\u043D\u0430\u043A\u0430 \u0438 \u0434\u0430 \u0432\u043A\u043B\u044E\u0447\u0432\u0430 \u0446\u0438\u0444\u0440\u0438 \u0438 \u0431\u0443\u043A\u0432\u0438. -form.checkUsername=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E\u0442\u043E \u0438\u043C\u0435 \u0442\u0440\u044F\u0431\u0432\u0430 \u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430 \u043F\u043E\u043D\u0435 4 \u0437\u043D\u0430\u043A\u0430 \u0438 \u0441\u0430\u043C\u043E \u0431\u0443\u043A\u0432\u0438 \u043E\u0442 \u0410 \u0434\u043E \u042F (\u0431\u0435\u0437 \u0443\u043C\u043B\u0430\u0443\u0442), \u043A\u0430\u043A\u0442\u043E \u0438 \u0446\u0438\u0444\u0440\u0438 \u043E\u0442 0 \u0434\u043E 9. \u0414\u043E\u043F\u044A\u043B\u043D\u0438\u0442\u0435\u043B\u043D\u043E, \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u0430 \u0438\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u0442\u0435 . _ \u0438 -. +form.checkUsername=\u041F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u0441\u043A\u043E\u0442\u043E \u0438\u043C\u0435 \u0442\u0440\u044F\u0431\u0432\u0430 \u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430 \u043F\u043E\u043D\u0435 4 \u0437\u043D\u0430\u043A\u0430 \u0438 \u0441\u0430\u043C\u043E \u0431\u0443\u043A\u0432\u0438 \u043E\u0442 \u0410 \u0434\u043E \u042F (\u0431\u0435\u0437 \u0443\u043C\u043B\u0430\u0443\u0442), \u043A\u0430\u043A\u0442\u043E \u0438 \u0446\u0438\u0444\u0440\u0438 \u043E\u0442 0 \u0434\u043E 9. \u0414\u043E\u043F\u044A\u043B\u043D\u0438\u0442\u0435\u043B\u043D\u043E, \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u0430 \u0438\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u0442\u0435 . @ _ \u0438 -. form.description=\u041C\u043E\u043B\u044F, \u043D\u0430\u043F\u0438\u0448\u0435\u0442\u0435 \u0432\u0430\u0448\u0438\u0442\u0435 \u043B\u0438\u0447\u043D\u0438 \u0434\u0430\u043D\u043D\u0438 \u0432\u044A\u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0430 \u043F\u043E-\u0434\u043E\u043B\u0443. \u0421 \u043F\u043E\u043C\u043E\u0449\u0430 \u043D\u0430 \u043A\u0443\u0442\u0438\u0438\u0442\u0435 \u0437\u0430 \u043E\u0442\u043C\u044F\u0442\u0430\u043D\u0435, \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u0430 \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u0435 \u043A\u043E\u0438 \u0432\u043F\u0438\u0441\u0432\u0430\u043D\u0438\u044F \u0449\u0435 \u0441\u0435 \u043F\u043E\u044F\u0432\u044F\u0432\u0430\u0442 \u043D\u0430 \u0432\u0430\u0448\u0430\u0442\u0430 \u0432\u0438\u0437\u0438\u0442\u043D\u0430 \u043A\u0430\u0440\u0442\u0438\u0447\u043A\u0430. form.email=\u0418-\u043C\u0435\u0439\u043B \u0430\u0434\u0440\u0435\u0441 form.fields=\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u0432\u043F\u0438\u0441\u0432\u0430\u043D\u0438\u044F diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_cs.properties index ea7d8c7f0b1..d74b60be7a5 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_cs.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_cs.properties @@ -13,8 +13,7 @@ error.password.noauth=Va\u0161e star\u00E9 heslo bylo zad\u00E1no chybn\u011B. error.password.nomatch=Nov\u00E1 hesla jsou r\u016Fzn\u00E1. form.address=Adresa form.charset=K\u00F3dovac\u00ED mapa pro stahov\u00E1n\u00ED -form.checkPassword=Heslo mus\u00ED obsahovat alespo\u0148 4 znaky a mus\u00ED obsahovat p\u00EDsmena a \u010D\u00EDsla. -form.checkUsername=U\u017Eivatelsk\u00E9 jm\u00E9no mus\u00ED obsahovat alespo\u0148 4 znaky od a do z (bez diakritiky) nebo \u010D\u00EDsla od 0 do 9. D\u00E1le m\u016F\u017Eete pou\u017E\u00EDvat . _ a -. +form.checkUsername=U\u017Eivatelsk\u00E9 jm\u00E9no mus\u00ED obsahovat alespo\u0148 4 znaky od a do z (bez diakritiky) nebo \u010D\u00EDsla od 0 do 9. D\u00E1le m\u016F\u017Eete pou\u017E\u00EDvat . @ _ a -. form.email=E-mailov\u00E1 adresa form.fields=Vybrat polo\u017Eky form.fontsize=Velikost fontu diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_da.properties index 3107f030e7f..3ce5a7dd5d5 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_da.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_da.properties @@ -13,8 +13,7 @@ error.password.noauth=Dit nuv\u00E6rende kodeord er ikke korrekt. error.password.nomatch=De to nye kodeord er ikke ens form.address=Adresse form.charset=Tegns\u00E6t benyttet i download -form.checkPassword=Kodeord skal indeholde mindst 4 tegn og inkludere b\u00E5de tal og bogstaver. -form.checkUsername=Brugernavnet skal v\u00E6re mindst 4 tegn og m\u00E5 kun indeholder bogstaver fra a-z og tal. Dog m\u00E5 du bruge punktum, understregning og bindestreg (._-). +form.checkUsername=Brugernavnet skal v\u00E6re mindst 4 tegn og m\u00E5 kun indeholder bogstaver fra a-z og tal. Dog m\u00E5 du bruge punktum, understregning og bindestreg (.@_-). form.fields=V\u00E6lg felter form.fontsize=Skriftst\u00F8rrelse form.fontsize.large=Stor diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties index 3605165cd62..e82479fa7a6 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties @@ -23,15 +23,15 @@ error.change.email.time=Dieser Aktivierungs-Link hat eine G\u00FCltigkeitsdauer error.change.email.unexpected=Ihre E-Mail Adresse konnte nicht ge\u00C4ndert werden. Ein unerwarteter Fehler ist aufgetreten. error.no.props.found=Es wurden keine Properties f\u00FCr diesen Benutzer gefunden error.password.empty=Geben Sie Ihr bisheriges Passwort an +error.password.invalid=Das Password ist nicht g\u00FCltig.{0} error.password.noauth=Ihr bisheriges Passwort ist nicht korrekt error.password.nomatch=Die beiden neuen Passw\u00F6rter stimmen nicht \u00FCberein. error.user.logged.in=Diese \u00C4nderung kann nicht vorgenommen werden da der Benutzer {0} zur Zeit eingeloggt ist. Warten Sie bis der Benutzer sich ausloggt und versuchen Sie es erneut. +error.username.invalid={0} extlink=Externer Link zur Visitenkarte form.address=Adresse form.charset=Zeichensatz f\u00FCr Download -form.checkPassword=Das Passwort muss mindestens 4 Zeichen haben. Verwenden Sie dabei sowohl Ziffern als auch Buchstaben. -form.checkPassword.history=Sie d\u00FCrfen nicht ein Passwort dass Sie schon hatten wieder verwenden. -form.checkUsername=Der Benutzername muss mindestens 4 Zeichen lang sein und darf nur Buchstaben von a bis z (keine Umlaute, keine Grossbuchstaben) und Ziffern von 0 bis 9 enthalten. Zus\u00E4tzlich sind die Sonderzeichen . _ und - erlaubt. +form.checkUsername=Der Benutzername muss mindestens 4 Zeichen lang sein und darf nur Buchstaben von a bis z (keine Umlaute, keine Grossbuchstaben) und Ziffern von 0 bis 9 enthalten. Zus\u00E4tzlich sind die Sonderzeichen . @ _ und - erlaubt. form.description=Geben Sie im untenstehenden Formular Ihre pers\u00F6nlichen Daten an. Unter "Meine Visitenkarte" bestimmen Sie mit Hilfe der Check-Boxen welche Eintr\u00E4ge auf Ihrer Visitenkarte erscheinen sollen. Dort finden Sie auch die Vorschau. form.email=E-Mail form.fields=Auswahl der Eintr\u00E4ge @@ -49,6 +49,7 @@ form.organisations=Organisationen form.password.new1=Neues OpenOLAT-Passwort form.password.new2=OLAT-Passwort best\u00E4tigen form.password.old=Bisheriges OpenOLAT-Passwort +form.password.validation.rules=Das neue Password muss folgende Kriterien erf\u00FCllen:{0} form.please.enter.new=Geben Sie bitte Ihr neues OpenOLAT-Passwort ein. form.please.enter.old=Geben Sie bitte Ihr bisheriges OpenOLAT-Passwort ein. form.text=Pers\u00F6nlicher Text @@ -93,12 +94,13 @@ propdelete.yesno.title=Sind Sie sicher? pwdav.access_data=<h4>Zugangsdaten</h4> pwdav.description=WebDAV erm\u00F6glicht Ihnen einen einfachen Dateitransfer von Ihrem Rechner zu OpenOLAT-Ordnern, wobei Sie mit Drag und Drop nebst einzelnen Dateien auch ganze Verzeichnisse in OpenOLAT-Ordner kopieren k\u00F6nnen. Um WebDAV zu nutzen, m\u00FCssen Sie auf Ihrem Computer ein Netzlaufwerk mit untenstehender Adresse anlegen\: pwdav.password=WebDAV-Passwort -pwdav.password.change=Passwort \u00C4ndern +pwdav.password.change=Passwort \u00E4ndern pwdav.password.confirm=WebDAV-Passwort best\u00E4tigen pwdav.password.failed=Ihr neues WebDAV Passwort wurde nicht gespeichert. Ein unerwarteter Fehler ist aufgetreten. pwdav.password.new=Passwort einrichten pwdav.password.not_set=<i>WebDAV Passwort nicht eingerichtet</i> pwdav.password.placeholder=<i>verwenden Sie Ihr OpenOLAT Passwort f\u00FCr den WebDAV Zugang</i> +pwdav.password.rules=$\:form.password.validation.rules pwdav.password.set=******* (Passwort verschl\u00FCsselt) pwdav.password.successful=Ihr neues WebDAV Passwort wurde erfolgreich gespeichert. Es ist ab sofort aktiv. pwdav.title=WebDAV Zugang diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_el.properties index b4f764cc2aa..1851674e917 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_el.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_el.properties @@ -25,8 +25,7 @@ error.password.noauth=\u039F \u03C0\u03B1\u03BB\u03B1\u03B9\u03CC\u03C2 \u03BA\u error.password.nomatch=\u039F\u03B9 \u03B4\u03CD\u03BF \u03BD\u03AD\u03BF\u03B9 \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03AF \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03B4\u03B5\u03BD \u03C4\u03B1\u03B9\u03C1\u03B9\u03AC\u03B6\u03BF\u03C5\u03BD. form.address=\u0394\u03B9\u03B5\u03CD\u03B8\u03C5\u03BD\u03C3\u03B7 form.charset=\u03A3\u03CD\u03BD\u03BF\u03BB\u03BF \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD \u03C0\u03BF\u03C5 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B1\u03B9 \u03BA\u03B1\u03C4\u03AC \u03C4\u03B7 \u03BB\u03AE\u03C8\u03B7 -form.checkPassword=\u039F \u03BA\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03C4\u03BF\u03C5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03BF\u03BD 4 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2 \u03BC\u03B5 \u03BB\u03B1\u03C4\u03B9\u03BD\u03B9\u03BA\u03AC \u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03B1 \u03AE \u03C8\u03B7\u03C6\u03AF\u03B1. -form.checkUsername=\u03A4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03C4\u03BF\u03C5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03BF\u03BD 4 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2 \u03BA\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4 \u03B1\u03C0\u03CC \u03C4\u03BF a \u03AD\u03C9\u03C2 \u03C4\u03BF z (\u03C7\u03C9\u03C1\u03AF\u03C2 \u03C3\u03B7\u03BC\u03B5\u03AF\u03B1 \u03C3\u03C4\u03AF\u03BE\u03B7\u03C2) \u03BA\u03B1\u03B8\u03CE\u03C2 \u03BA\u03B1\u03B9 \u03C8\u03B7\u03C6\u03AF\u03B1 \u03B1\u03C0\u03CC \u03C4\u03BF 0 \u03AD\u03C9\u03C2 \u03C4\u03BF 9. \u0395\u03C0\u03B9\u03C0\u03BB\u03AD\u03BF\u03BD \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03B5\u03C4\u03B5 \u03C4\u03BF\u03C5\u03C2 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2 . _ \u03BA\u03B1\u03B9 -. +form.checkUsername=\u03A4\u03BF \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03C4\u03BF\u03C5\u03BB\u03AC\u03C7\u03B9\u03C3\u03C4\u03BF\u03BD 4 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2 \u03BA\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4 \u03B1\u03C0\u03CC \u03C4\u03BF a \u03AD\u03C9\u03C2 \u03C4\u03BF z (\u03C7\u03C9\u03C1\u03AF\u03C2 \u03C3\u03B7\u03BC\u03B5\u03AF\u03B1 \u03C3\u03C4\u03AF\u03BE\u03B7\u03C2) \u03BA\u03B1\u03B8\u03CE\u03C2 \u03BA\u03B1\u03B9 \u03C8\u03B7\u03C6\u03AF\u03B1 \u03B1\u03C0\u03CC \u03C4\u03BF 0 \u03AD\u03C9\u03C2 \u03C4\u03BF 9. \u0395\u03C0\u03B9\u03C0\u03BB\u03AD\u03BF\u03BD \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03B5\u03C4\u03B5 \u03C4\u03BF\u03C5\u03C2 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2 . @ _ \u03BA\u03B1\u03B9 -. form.description=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03B9\u03C3\u03AC\u03B3\u03B5\u03C4\u03B5 \u03C4\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03AC \u03C3\u03B1\u03C2 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03B1 \u03C3\u03C4\u03B7\u03BD \u03C0\u03B1\u03C1\u03B1\u03BA\u03AC\u03C4\u03C9 \u03C6\u03CC\u03C1\u03BC\u03B1. \u039C\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03BF\u03C1\u03AF\u03C3\u03B5\u03C4\u03B5 \u03C4\u03B9\u03C2 \u03BA\u03B1\u03C4\u03B1\u03C7\u03C9\u03C1\u03AE\u03C3\u03B5\u03B9\u03C2 \u03C0\u03BF\u03C5 \u03B5\u03BC\u03C6\u03B1\u03BD\u03AF\u03B6\u03BF\u03BD\u03C4\u03B1\u03B9 \u03C3\u03C4\u03B7\u03BD \u03BA\u03AC\u03C1\u03C4\u03B1 \u03B5\u03C0\u03B9\u03C3\u03BA\u03AD\u03C0\u03C4\u03B7 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03CE\u03BD\u03C4\u03B1\u03C2 \u03C4\u03B1 \u03BA\u03BF\u03C5\u03C4\u03B9\u03AC \u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE\u03C2. form.email=\u0394\u03B9\u03B5\u03CD\u03B8\u03C5\u03BD\u03C3\u03B7 E-mail form.fields=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u03BA\u03B1\u03C1\u03B1\u03C7\u03C9\u03C1\u03AE\u03C3\u03B5\u03C9\u03BD diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties index 37d2e15cf45..00f65d75eb3 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties @@ -23,15 +23,15 @@ error.change.email.time=This activating link can only be used for {0} hrs and is error.change.email.unexpected=Your E-mail could not be changed. An unexpected server error occurred. error.no.props.found=No properties found for this user error.password.empty=Please indicate your previous password +error.password.invalid=The password is not valid.{0} error.password.noauth=Your previous password is inaccurate error.password.nomatch=The two new passwords do not match. error.user.logged.in=This change can not be made as the user {0} is currently logged in. Please wait until the user has logged out and try it again. +error.username.invalid={0} extlink=External link to visiting card form.address=Address form.charset=Character set used in download -form.checkPassword=Your password must contain at least 4 characters and include digits and letters. -form.checkPassword.history=You cannot use a password you already used in the past. -form.checkUsername=User names have to contain at least 4 characters and only letters from a to z (no umlaut or capital letters) as well as digits from 0 to 9. Additionally you may use . _ and -. +form.checkUsername=User names have to contain at least 4 characters and only letters from a to z (no umlaut or capital letters) as well as digits from 0 to 9. Additionally you may use . @ _ and -. form.description=Please indicate your personal data in the form below. By means of check boxes you can determine the entries that should appear on your visiting card. form.email=E-mail form.fields=Selection of entries @@ -49,6 +49,7 @@ form.organisations=Organisations form.password.new1=New OpenOLAT password form.password.new2=Confirm OpenOLAT password form.password.old=Old OpenOLAT password +form.password.validation.rules=The new password must meet the following criteria:{0} form.please.enter.new=Please enter your new OpenOLAT password. form.please.enter.old=Please enter your old OpenOLAT password. form.text=Personal text @@ -99,6 +100,7 @@ pwdav.password.failed=Your new WebDAV password could not be saved. An unexpected pwdav.password.new=Set password pwdav.password.not_set=<i>WebDAV password not set</i> pwdav.password.placeholder=<i>Please use your OpenOLAT password to access WebDAV</i> +pwdav.password.rules=$\:form.password.validation.rules pwdav.password.set=******* (password encoded) pwdav.password.successful=Your new WebDAV password has been saved successfully. It is valid from now on. pwdav.title=WebDAV access diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_es.properties index ae7dd65a812..718185f3a03 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_es.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_es.properties @@ -25,8 +25,7 @@ error.password.noauth=Tu anterior contrase\u00F1a no es correcta. error.password.nomatch=Las dos contrase\u00F1as nuevas no coinciden. form.address=Direcci\u00F3n form.charset=Conjunto de caracteres utilizados en la descarga -form.checkPassword=La contrase\u00F1a debe contener al menos 4 caracteres e incluir d\u00EDgitos y letras. -form.checkUsername=El nombre de usuario debe contener al menos 4 caracteres y s\u00F3lo letras de la 'a' a la 'z' (sin di\u00E9resis ni acentos) asi como n\u00FAmeros de 0 a 9. Adiccionalmente puedes utilizar . _ y -. +form.checkUsername=El nombre de usuario debe contener al menos 4 caracteres y s\u00F3lo letras de la 'a' a la 'z' (sin di\u00E9resis ni acentos) asi como n\u00FAmeros de 0 a 9. Adiccionalmente puedes utilizar . @ _ y -. form.description=Por favor, indique sus datos personales en el formulario de abajo. Por medio de las casillas de verificaci\u00F3n se puede determinar las entradas que deben aparecer en su tarjeta de visita. form.email=E-mail form.fields=Seleccionar entradas diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_fa.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_fa.properties index 6e750912c15..341898400db 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_fa.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_fa.properties @@ -13,7 +13,6 @@ error.password.noauth=\u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 \u0642\u error.password.nomatch=\u062F\u0648 \u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 \u062C\u062F\u06CC\u062F \u0645\u0637\u0627\u0628\u0642\u062A \u0646\u062F\u0627\u0631\u062F form.address=\u0622\u062F\u0631\u0633 form.charset=Character set used in download -form.checkPassword=\u06A9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631 \u0628\u0627\u06CC\u062F \u062D\u062F\u0627\u0642\u0644 \u0634\u0627\u0645\u0644 4 \u06A9\u0627\u0631\u0627\u06A9\u062A\u0631\u0645\u062A\u0634\u06A9\u0644 \u0627\u0632 \u062D\u0631\u0648\u0641 \u0648 \u0627\u0639\u062F\u0627\u062F \u0628\u0627\u0634\u062F form.fields=\u0627\u0646\u062A\u062E\u0627\u0628 \u0645\u062F\u062E\u0644 form.fontsize=\u0627\u0646\u062F\u0627\u0632\u0647 \u0641\u0648\u0646\u062A form.fontsize.large=\u0628\u0632\u0631\u06AF diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_fr.properties index 97942be7e32..94b1db1a0d2 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_fr.properties @@ -29,9 +29,7 @@ error.user.logged.in=Ce changement ne peut pas \u00EAtre effectu\u00E9e pour l'i extlink=Lien externe vers la carte de visite form.address=Adresse form.charset=Jeu de caract\u00E8res pour t\u00E9l\u00E9chargement -form.checkPassword=Le mot de passe doit contenir au moins quatre caract\u00E8res. Utilisez des lettres ET des chiffres. -form.checkPassword.history=Vous ne pouvez pas r\u00E9utiliser un mot de passe que vous avez d\u00E9j\u00E0 utilis\u00E9 par le pass\u00E9. -form.checkUsername=Le nom d'utilisateur doit \u00EAtre compos\u00E9 d'au moins 4 caract\u00E8res et ne doit contenir que des lettres de A \u00E0 Z (sans accents) et des chiffres de 0 \u00E0 9. En plus les caract\u00E8res sp\u00E9ciaux . _ et - sont permis. +form.checkUsername=Le nom d'utilisateur doit \u00EAtre compos\u00E9 d'au moins 4 caract\u00E8res et ne doit contenir que des lettres de A \u00E0 Z (sans accents) et des chiffres de 0 \u00E0 9. En plus les caract\u00E8res sp\u00E9ciaux . @ _ et - sont permis. form.description=Indiquez vos donn\u00E9es personnelles dans le formulaire ci-dessous. Vous pouvez d\u00E9cider laquelle des entr\u00E9es sera visible sur votre carte de visite gr\u00E2ce au bo\u00EEtes \u00E0 cocher. form.email=E-mail form.fields=S\u00E9lection des entr\u00E9es diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_it.properties index c3a0cf09cb8..16562695307 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_it.properties @@ -28,8 +28,7 @@ error.user.logged.in=Questo cambiamento non pu\u00F2 essere effettuato poich\u00 extlink=Link esterno al biglietto da visita form.address=Indirizzo form.charset=Set di caratteri per lo scaricamento -form.checkPassword=La password deve contenere almeno 4 segni. Utilizzi sia cifre che lettere. -form.checkUsername=Il nome d'utente deve contenere almeno 4 segni e consistere solo di lettere dalla a alla z (senza '\u00E4', '\u00F6' ecc.) e cifre da 0 a 9. In aggiunta sono permessi i segni speciali . _ e -. +form.checkUsername=Il nome d'utente deve contenere almeno 4 segni e consistere solo di lettere dalla a alla z (senza '\u00E4', '\u00F6' ecc.) e cifre da 0 a 9. In aggiunta sono permessi i segni speciali . @ _ e -. form.description=Indichi nel formulario sottostante i Suoi dati personali, p.f. Utilizzando le caselle a selezione pu\u00F2 stabilire quali informazioni saranno visibili sul Suo biglietto da visita. form.email=E-mail form.fields=Selezione delle entrate diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_jp.properties index 26d2433e320..5e20a56cf3d 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_jp.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_jp.properties @@ -19,8 +19,6 @@ error.password.noauth=\u3042\u306A\u305F\u306E\u524D\u306E\u30D1\u30B9\u30EF\u30 error.password.nomatch=2\u3064\u306E\u65B0\u3057\u3044\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5408\u81F4\u3057\u307E\u305B\u3093\u3002 form.address=\u4F4F\u6240 form.charset=\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u306B\u4F7F\u7528\u3059\u308B\u6587\u5B57\u30BB\u30C3\u30C8 -form.checkPassword=\u3042\u306A\u305F\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u3001\u6570\u5B57\u304A\u3088\u3073\u6587\u5B57\u3092\u542B\u3080\u3001\u5C11\u306A\u304F\u3068\u30824\u6587\u5B57\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 -form.checkUsername=\u30E6\u30FC\u30B6\u540D\u306B\u306F\u5C11\u306A\u304F\u3068\u3082\u534A\u89D24\u6587\u5B57\u3092\u542B\u307F\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u6570\u5B570\u304B\u30899\u304A\u3088\u3073A\u304B\u3089Z (\u30A6\u30E0\u30E9\u30A6\u30C8\u306A\u3057) \u306E\u6587\u5B57\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\u307E\u305F\u3001\u3042\u306A\u305F\u306F\u300C.\u300D\u300C_\u300D\u300C-\u300D\u3092\u4F7F\u7528\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002 form.description=\u4E0B\u8A18\u306E\u30D5\u30A9\u30FC\u30E0\u306B\u3001\u3042\u306A\u305F\u306E\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9\u3092\u4F7F\u7528\u3059\u308B\u3053\u3068\u3067\u3001\u3042\u306A\u305F\u306E\u30D3\u30B8\u30C6\u30A3\u30F3\u30B0\u30AB\u30FC\u30C9\u306B\u8868\u793A\u3059\u308B\u30A8\u30F3\u30C8\u30EA\u3092\u6307\u5B9A\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002 form.email=E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9 form.fields=\u30A8\u30F3\u30C8\u30EA\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002 diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_lt.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_lt.properties index e72ee8fc1a5..c62f0b44b19 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_lt.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_lt.properties @@ -13,8 +13,7 @@ error.password.noauth=J\u016Bs\u0173 senas slapta\u017Eodis n\u0117ra teisingas. error.password.nomatch=Du nauji slapta\u017Eod\u017Eiai neatitinka. form.address=Adresas form.charset=\u017Denkl\u0173 rinkinys naudojamas siun\u010Diantis -form.checkPassword=Slapta\u017Eod\u012F turi sudaryti ma\u017Eiausiai 4 simboliai \u012Ftraukiant skai\u010Dius ir raides. -form.checkUsername=Vartotojo vard\u0105 turi sudaryti ma\u017Eiausiai 4 simboliai, raid\u0117s\: a-z (be umliaut\u0173), skai\u010Diai\: 0-9. J\u016Bs galite naudoti . _ ir -. +form.checkUsername=Vartotojo vard\u0105 turi sudaryti ma\u017Eiausiai 4 simboliai, raid\u0117s\: a-z (be umliaut\u0173), skai\u010Diai\: 0-9. J\u016Bs galite naudoti . @ _ ir -. form.fields=Pa\u017Eym\u0117kite \u012Fvestis form.fontsize=\u0160rifto dydis form.fontsize.large=Didelis diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_nl_NL.properties index 64d60109315..50459941002 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_nl_NL.properties @@ -25,8 +25,6 @@ error.password.noauth=Uw vorige wachtwoord is niet correct error.password.nomatch=De twee nieuwe wachtwoorden komen niet overeen. form.address=Adres form.charset=Tekenset gebruikt bij download -form.checkPassword=Uw wachtwoord moet minstens 4 tekens bevatten en moet bestaan uit cijfers en letters. -form.checkUsername=De gebruikersnaam moet op zijn minst 4 tekens bevatten en moet zowel bestaan uit letters van A tot Z (zonder umlautsteken) als uit cijfers van 0 tot 9. Ook mag u ._ en -. gebruiken. form.description=Gelieve uw persoonlijke data in te geven in het onderstaande formulier. Doormiddel van de check-boxen kunt u bepalen welke gegevens moeten verschijnen op uw visitekaartje. form.email=E-mailadres form.fields=Kies gegevens diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_pl.properties index a4893bac1e5..78e57a36ae9 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_pl.properties @@ -25,8 +25,7 @@ error.password.noauth=Stare has\u0142o jest nieprawid\u0142owe error.password.nomatch=Nowe has\u0142a nie pasuj\u0105 form.address=Adres form.charset=Zbi\u00F3r znak\u00F3w u\u017Cywany podczas pobierania plik\u00F3w -form.checkPassword=Has\u0142o musi zawiera\u0107 co najmniej 4 znaki, w tym litery i cyfry. -form.checkUsername=Nazwa u\u017Cytkownika musi zawiera\u0107 co najmniej 4 znaki- litery od a do z i cyfry od 0 do 9. Dodatkowo mo\u017Cesz u\u017Cy\u0107 . _ i - +form.checkUsername=Nazwa u\u017Cytkownika musi zawiera\u0107 co najmniej 4 znaki- litery od a do z i cyfry od 0 do 9. Dodatkowo mo\u017Cesz u\u017Cy\u0107 . @ _ i - form.description=Uzupe\u0142nij swoje dane osobowe w formularzu poni\u017Cej. Za pomoc\u0105 pola wyboru mo\u017Cna okre\u015Bli\u0107 pozycje, kt\u00F3re powinny znajdowa\u0107 si\u0119 na Twojej wizyt\u00F3wce. form.email=Adres e-mail form.fields=Wybierz wpisy diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_pt_BR.properties index 60a036035db..9d646c60080 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_pt_BR.properties @@ -29,9 +29,7 @@ error.user.logged.in=Esta mudan\u00E7a n\u00E3o pode ser feita pois o usu\u00E1r extlink=Link externo para cart\u00E3o de visita form.address=Endere\u00E7o form.charset=Cadeia de caracteres utilizada no download -form.checkPassword=A senha deve conter pelo menos 4 caracteres e incluir d\u00EDgitos e letras -form.checkPassword.history=Voc\u00EA n\u00E3o pode usar uma senha que j\u00E1 usou no passado. -form.checkUsername=O nome de usu\u00E1rio tem que ter pelo menos 4 caracteres e somente letras de a a z (min\u00FAsculas) bem como d\u00EDgitos de 0 a 9. Adicionalmente voc\u00EA pode usar . _ e -. +form.checkUsername=O nome de usu\u00E1rio tem que ter pelo menos 4 caracteres e somente letras de a a z (min\u00FAsculas) bem como d\u00EDgitos de 0 a 9. Adicionalmente voc\u00EA pode usar . @ _ e -. form.description=Indique os seus dados pessoais no formul\u00E1rio abaixo. Atrav\u00E9s das lacunas voc\u00EA pode determinar as entradas que devem aparecer no seu cart\u00E3o de visita. form.email=Endere\u00E7o de E-mail form.fields=Selecionar itens diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_pt_PT.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_pt_PT.properties index 51a44bce563..3942be6e81d 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_pt_PT.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_pt_PT.properties @@ -13,8 +13,7 @@ error.password.noauth=Sua senha antiga est\u00E1 incorreta error.password.nomatch=As duas novas senhas n\u00E3o coincidem form.address=Endere\u00E7o form.charset=Cadeia de caracteres utilizada no download -form.checkPassword=A senha deve conter pelo menos 4 caracteres e incluir d\u00EDgitos e letras -form.checkUsername=O nome de usu\u00E1rio tem que ter pelo menos 4 caracteres e somente letras de a a z (min\u00FAsculas) bem como d\u00EDgitos de 0 a 9. Adicionalmente voc\u00EA pode usar . _ e -. +form.checkUsername=O nome de usu\u00E1rio tem que ter pelo menos 4 caracteres e somente letras de a a z (min\u00FAsculas) bem como d\u00EDgitos de 0 a 9. Adicionalmente voc\u00EA pode usar . @ _ e -. form.fields=Selecionar itens form.fontsize=Tamanho de fonte form.fontsize.large=Grande diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_ru.properties index 69c104f9b99..e6773780a23 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_ru.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_ru.properties @@ -25,8 +25,7 @@ error.password.noauth=\u0412\u0430\u0448 \u0441\u0442\u0430\u0440\u044B\u0439 \u error.password.nomatch=\u041E\u0431\u0430 \u043D\u043E\u0432\u044B\u0445 \u043F\u0430\u0440\u043E\u043B\u044F \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0442. form.address=\u0410\u0434\u0440\u0435\u0441 form.charset=\u041A\u043E\u0434\u0438\u0440\u043E\u0432\u043A\u0430 \u0434\u043B\u044F \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F -form.checkPassword=\u041F\u0430\u0440\u043E\u043B\u044C \u0434\u043E\u043B\u0436\u0435\u043D \u0441\u043E\u0441\u0442\u043E\u044F\u0442\u044C \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C \u0438\u0437 4-\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432. \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043F\u0440\u0438 \u044D\u0442\u043E\u043C \u043A\u0430\u043A \u0447\u0438\u0441\u043B\u0430, \u0442\u0430\u043A \u0438 \u0431\u0443\u043A\u0432\u044B. -form.checkUsername=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0434\u043E\u043B\u0436\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C 4 \u0441\u0438\u043C\u0432\u043E\u043B\u0430 \u0438 \u0441\u043E\u0441\u0442\u043E\u044F\u0442\u044C \u0438\u0437 \u0431\u0443\u043A\u0432 \u043E\u0442 \u0430 \u0434\u043E \u044F (\u0431\u0435\u0437 \u0437\u0430\u0433\u043B\u0430\u0432\u043D\u044B\u0445 \u0431\u0443\u043A\u0432) \u0438 \u0446\u0438\u0444\u0440 \u043E\u0442 0 \u0434\u043E 9. \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u0442\u0430\u043A\u0438\u0445 \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432 \u043A\u0430\u043A . _ \u0438 - . +form.checkUsername=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0434\u043E\u043B\u0436\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C 4 \u0441\u0438\u043C\u0432\u043E\u043B\u0430 \u0438 \u0441\u043E\u0441\u0442\u043E\u044F\u0442\u044C \u0438\u0437 \u0431\u0443\u043A\u0432 \u043E\u0442 \u0430 \u0434\u043E \u044F (\u0431\u0435\u0437 \u0437\u0430\u0433\u043B\u0430\u0432\u043D\u044B\u0445 \u0431\u0443\u043A\u0432) \u0438 \u0446\u0438\u0444\u0440 \u043E\u0442 0 \u0434\u043E 9. \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u0442\u0430\u043A\u0438\u0445 \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432 \u043A\u0430\u043A . @ _ \u0438 - . form.description=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0444\u043E\u0440\u043C\u0443\u043B\u044F\u0440 \u0412\u0430\u0448\u0438 \u043F\u0435\u0440\u0441\u043E\u043D\u0430\u043B\u044C\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435. \u0421 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u043E\u043A\u043E\u0448\u0435\u043A \u0434\u043B\u044F \u0432\u044B\u0431\u043E\u0440\u0430 \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C, \u0447\u0442\u043E \u0434\u043E\u043B\u0436\u043D\u043E \u043F\u043E\u044F\u0432\u0438\u0442\u044C\u0441\u044F \u043D\u0430 \u0412\u0430\u0448\u0435\u0439 \u0432\u0438\u0437\u0438\u0442\u043D\u043E\u0439 \u043A\u0430\u0440\u0442\u043E\u0447\u043A\u0435. form.email=E-mail \u0430\u0434\u0440\u0435\u0441 form.fields=\u0412\u044B\u0431\u043E\u0440 \u0434\u0430\u043D\u043D\u044B\u0445 diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_sq.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_sq.properties index 597ef8abd35..a8149b74918 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_sq.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_sq.properties @@ -13,8 +13,7 @@ error.password.noauth=Fjal\u00EBkalimi juaj i vjet\u00EBr nuk \u00EBsht\u00EB i error.password.nomatch=Dy fjal\u00EBkalimet e reja nuk p\u00EBrputhen. form.address=Adresa form.charset=karakteret e shfryt\u00EBzuara gjat\u00EB shkarkimit -form.checkPassword=Fjal\u00EBkalimi duhet t\u00EB p\u00EBrmbaj t\u00EB pakt\u00EBn 4 shkronja dhe t\u00EB p\u00EBrfshij numra dhe shkronja. -form.checkUsername=Emri i shfryt\u00EBzuesit duhet t\u00EB p\u00EBrmbaj\u00EB s\u00EB paku 4 karaktere dhe shkronja vet\u00EBm prej a deri n\u00EB zh (pa dyshim zanoreje) si dhe numrat prej 0 deri n\u00EB 9. Poashtu ju mund t\u00EB shfryt\u00EBzoni . _ dhe -. +form.checkUsername=Emri i shfryt\u00EBzuesit duhet t\u00EB p\u00EBrmbaj\u00EB s\u00EB paku 4 karaktere dhe shkronja vet\u00EBm prej a deri n\u00EB zh (pa dyshim zanoreje) si dhe numrat prej 0 deri n\u00EB 9. Poashtu ju mund t\u00EB shfryt\u00EBzoni . @ _ dhe -. form.fields=Zgjedh hyrjet form.fontsize=Madh\u00EBsia e shkronjave form.fontsize.large=T\u00EB m\u00EBdhaja diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_zh_CN.properties index b2a11128f97..53ec1e70119 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_zh_CN.properties @@ -27,8 +27,6 @@ error.user.logged.in=\u7531\u4E8E\u7528\u6237\u5DF2\u767B\u5F55\uFF0C\u4E0D\u80F extlink=\u540D\u7247\u7684\u5916\u90E8\u94FE\u63A5 form.address=\u5730\u5740 form.charset=\u5728\u4E0B\u8F7D\u4E2D\u7528\u5230\u7684\u5B57\u7B26\u96C6 -form.checkPassword=\u5BC6\u7801\u5FC5\u987B\u5305\u542B\u81F3\u5C114\u4E2A\u5B57\u7B26\uFF0C\u4E14\u5FC5\u987B\u5305\u542B\u5B57\u7B26\u548C\u6570\u5B57\u3002 -form.checkUsername=\u7528\u6237\u540D\u81F3\u5C11\u5305\u542B4\u4E2A\u5B57\u7B26\uFF0C\u4E14\u53EA\u80FD\u662Fa-z\u7684\u5B57\u6BCD\u548C0-9\u7684\u6570\u5B57\u3002\u6B64\u5916\uFF0C\u60A8\u53EF\u4EE5\u4F7F\u7528 . _\u548C -\u3002 form.description=\u8BF7\u5728\u4E0B\u9762\u7684\u8868\u683C\u4E2D\u8868\u660E\u4F60\u7684\u4E2A\u4EBA\u4FE1\u606F\u3002\u901A\u8FC7\u70B9\u51FB\u590D\u9009\u6846\u4F60\u53EF\u4EE5\u51B3\u5B9A\u8FD9\u4E9B\u6761\u76EE\u662F\u5426\u51FA\u73B0\u5728\u4F60\u7684\u8BBF\u95EE\u5361\u7247\u4E0A\u3002 form.email=e-mail\u5730\u5740 form.fields=\u9009\u62E9\u6761\u76EE diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_zh_TW.properties index bfa0ab7c900..baa7b355fe0 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_zh_TW.properties @@ -24,8 +24,7 @@ error.password.noauth=\u60A8\u7684\u820A\u5BC6\u78BC\u4E0D\u6B63\u78BA error.password.nomatch=\u9019\u5169\u500B\u65B0\u7684\u5BC6\u78BC\u4E26\u4E0D\u76F8\u7B26\u3002 form.address=\u5730\u5740 form.charset=\u4E0B\u8F09\u6642\u4F7F\u7528\u7684\u5B57\u5143\u96C6 -form.checkPassword=\u60A8\u7684\u5BC6\u78BC\u5FC5\u9808\u5305\u542B\u81F3\u5C11 4 \u500B\u5B57\u5143\u4E26\u4E14\u5305\u542B\u6578\u5B57\u548C\u5B57\u6BCD\u3002 -form.checkUsername=\u4F7F\u7528\u8005\u540D\u7A31\u5FC5\u9808\u5305\u542B\u81F3\u5C11 4 \u500B\u5B57\u5143\uFF0C\u4E14\u53EA\u6709\u5F9E A \u5230 Z (\u7121\u8B8A\u97F3) \u7684\u5B57\u6BCD\u4EE5\u53CA\u5F9E 0 \u5230 9 \u7684\u6578\u5B57\u3002\u6B64\u5916\uFF0C\u60A8\u53EF\u4EE5\u4F7F\u7528 . _ \u548C -\u3002 +form.checkUsername=\u4F7F\u7528\u8005\u540D\u7A31\u5FC5\u9808\u5305\u542B\u81F3\u5C11 4 \u500B\u5B57\u5143\uFF0C\u4E14\u53EA\u6709\u5F9E A \u5230 Z (\u7121\u8B8A\u97F3) \u7684\u5B57\u6BCD\u4EE5\u53CA\u5F9E 0 \u5230 9 \u7684\u6578\u5B57\u3002\u6B64\u5916\uFF0C\u60A8\u53EF\u4EE5\u4F7F\u7528 . @ _ \u548C -\u3002 form.description=\u8ACB\u5728\u4E0B\u5217\u7684\u8868\u55AE\u4E2D\u8F38\u5165\u60A8\u7684\u500B\u4EBA\u8CC7\u6599\u3002\u85C9\u7531\u6838\u9078\u65B9\u584A\u60A8\u53EF\u4EE5\u6C7A\u5B9A\u90A3\u4E9B\u9805\u76EE\u61C9\u8A72\u51FA\u73FE\u5728\u60A8\u7684\u540D\u7247\u4E0A\u3002 form.email=\u96FB\u5B50\u90F5\u4EF6\u5730\u5740 form.fields=\u9078\u64C7\u9805\u76EE diff --git a/src/main/java/org/olat/user/_spring/userContext.xml b/src/main/java/org/olat/user/_spring/userContext.xml index ea993cc035b..978ba29060c 100644 --- a/src/main/java/org/olat/user/_spring/userContext.xml +++ b/src/main/java/org/olat/user/_spring/userContext.xml @@ -248,9 +248,6 @@ <bean id="userManager" class="org.olat.user.UserManagerImpl" > <property name="userPropertiesConfig"> <ref bean="org.olat.user.UserPropertiesConfig" /> - </property> - <property name="userNameAndPasswordSyntaxChecker"> - <ref bean="org.olat.user.UserNameAndPasswordSyntaxChecker"/> </property> <property name="userDisplayNameCreator"> <ref bean="${userDisplayName}"/> @@ -260,14 +257,6 @@ <bean id="org.olat.core.commons.creator.UserAvatarDisplayControllerCreator" class="org.olat.user.UserAvatarDisplayControllerCreatorImpl"/> - <!-- Generic regexp based email and password checker. - If you customize this, make sure you adjusted the i18n keys - form.checkUsername - form.checkPassword - of the package org.olat.user - --> - <bean id="org.olat.user.UserNameAndPasswordSyntaxChecker" class="org.olat.user.UserNameAndPasswordSyntaxCheckerWithEmail" /> - <bean id="personalFolderManager" class="org.olat.user.PersonalFolderManager"/> <bean class="org.olat.user.DisplayPortraitManager"/> diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 3b71e76d8af..c46a6eac9e2 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -214,10 +214,39 @@ invitation.login=${login.invitationLogin} # Allow users to login using alternatively their email address or username login.using.username.or.email.enabled=true + +# Regex to validate username of new users. If yo change this property, +# Make sure to change the translation of $org.olat.user\:form.checkUsername accordingly. +username.regex=[0-9a-z\\.\\-@_]{4,32} + # permit users to change their own passwords # (if you set this to false, nobody can can change their pws!) password.change.allowed=true +# Password syntax checks +password.min.length=4 +password.max.length=128 + +# Values to restrict letters, digits and special signs +# atLeastX: min X letters (X = 1/2/3) +# disabled: The check is disabled. Letters/Digits/Specials are allowd in any quantity +# forbidden: Letters/Digits/Specials not allowed +# validateSeparately: Ignore this rule and use password.min.letters.uppercase / password.min.letters.lowercase instead + +# By default, a password has to have at least one letter. +password.letters=atLeast1 +password.letters.uppercase=disabled +password.letters.lowercase=disabled +# By default, a password has to have at least one digit or special sign. +password.digits.special.signs=atLeast1 +password.digits=disabled +password.special.signs=disabled + +# Are these values forbidden as part of the password? +password.forbidden.username=false +password.forbidden.firstname=false +password.forbidden.lastname=false + # Password ageing policy password.change.valid.hours.gui=48 password.change.valid.hours.rest=720 diff --git a/src/test/java/org/olat/login/validation/PasswordSyntaxValidatorTest.java b/src/test/java/org/olat/login/validation/PasswordSyntaxValidatorTest.java new file mode 100644 index 00000000000..b1805fcdc80 --- /dev/null +++ b/src/test/java/org/olat/login/validation/PasswordSyntaxValidatorTest.java @@ -0,0 +1,138 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.olat.login.validation.TestingRuleProvider.of; + +import java.util.List; + +import org.assertj.core.api.SoftAssertions; +import org.junit.Test; +import org.olat.core.id.Identity; +import org.olat.login.validation.SyntaxValidator; +import org.olat.login.validation.ValidationDescription; +import org.olat.login.validation.ValidationResult; +import org.olat.login.validation.ValidationRule; + +/** + * + * Initial date: 13 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class PasswordSyntaxValidatorTest { + + @Test + public void shouldValidateTrue() { + ValidationRule rule1 = new BooleanRule(true); + ValidationRule rule2 = new BooleanRule(true); + SyntaxValidator sut = new SyntaxValidator(of(rule1, rule2), true); + + ValidationResult result = sut.validate("123", null); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(result.isValid()).isTrue(); + softly.assertThat(result.getInvalidDescriptions()).isEmpty(); + softly.assertAll(); + } + + @Test + public void shouldValidateFalse() { + ValidationRule rule1 = new BooleanRule(true); + ValidationRule rule2 = new BooleanRule(false); + SyntaxValidator sut = new SyntaxValidator(of(rule1, rule2), true); + + ValidationResult result = sut.validate("123", null); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(result.isValid()).isFalse(); + softly.assertThat(result.getInvalidDescriptions()).hasSize(1); + softly.assertAll(); + } + + @Test + public void shouldValidateAll() { + ValidationRule rule1 = new BooleanRule(false); + ValidationRule rule2 = new BooleanRule(false); + SyntaxValidator sut = new SyntaxValidator(of(rule1, rule2), true); + + ValidationResult result = sut.validate("123", null); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(result.isValid()).isFalse(); + softly.assertThat(result.getInvalidDescriptions()).hasSize(2); + softly.assertAll(); + } + + @Test + public void shouldBreakOnFirsInvalidRule() { + ValidationRule rule1 = new BooleanRule(false); + ValidationRule rule2 = new BooleanRule(false); + SyntaxValidator sut = new SyntaxValidator(of(rule1, rule2), false); + + ValidationResult result = sut.validate("123", null); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(result.isValid()).isFalse(); + softly.assertThat(result.getInvalidDescriptions()).hasSize(1); + softly.assertAll(); + } + + + @Test + public void shouldGetAllDescriptions() { + ValidationRule rule1 = new BooleanRule(true); + ValidationRule rule2 = new BooleanRule(true); + SyntaxValidator sut = new SyntaxValidator(of(rule1, rule2), true); + + List<ValidationDescription> allDescriptions = sut.getAllDescriptions(); + + assertThat(allDescriptions).hasSize(2); + } + + + private static class BooleanRule implements ValidationRule { + + private final boolean valid; + + private BooleanRule(boolean valid) { + this.valid = valid; + } + + @Override + public boolean validate(String value, Identity identity) { + return valid; + } + + @Override + public ValidationDescription getDescription() { + return mock(ValidationDescription.class); + } + + @Override + public boolean isIdentityRule() { + return false; + } + + } + +} diff --git a/src/test/java/org/olat/login/validation/PasswordValidationRuleFactoryTest.java b/src/test/java/org/olat/login/validation/PasswordValidationRuleFactoryTest.java new file mode 100644 index 00000000000..36f380c27e9 --- /dev/null +++ b/src/test/java/org/olat/login/validation/PasswordValidationRuleFactoryTest.java @@ -0,0 +1,390 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.assertj.core.api.SoftAssertions; +import org.junit.Test; +import org.mockito.Mock; +import org.olat.core.gui.translator.Translator; +import org.olat.core.id.Identity; +import org.olat.core.id.User; +import org.olat.login.validation.PasswordValidationRuleFactory; +import org.olat.login.validation.ValidationRule; + +/** + * + * Initial date: 12 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class PasswordValidationRuleFactoryTest { + + @Mock + private Identity iMock = mock(Identity.class); + + PasswordValidationRuleFactory sut = new TestableValidationRuleFactory(); + + @Test + public void shouldCreateVisibleCharactersRule() { + ValidationRule rule = sut.createVisibleCharactersRule(4, 7); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("12", iMock)).isFalse(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("1234", iMock)).isTrue(); + softly.assertThat(rule.validate("12345", iMock)).isTrue(); + softly.assertThat(rule.validate("123456", iMock)).isTrue(); + softly.assertThat(rule.validate("1234567", iMock)).isTrue(); + softly.assertThat(rule.validate("12345678", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("üäö", iMock)).isFalse(); + softly.assertThat(rule.validate("abcdefghi", iMock)).isFalse(); + softly.assertThat(rule.validate("ab cd", iMock)).isFalse(); + softly.assertThat(rule.validate("abcd e", iMock)).isFalse(); + softly.assertThat(rule.validate("ab\ncd", iMock)).isFalse(); + softly.assertThat(rule.validate("\\u0001\\u0001\\u0001\\u0001\\u0001", iMock)).isFalse(); + softly.assertThat(rule.validate("abcd", iMock)).isTrue(); + softly.assertThat(rule.validate("()%&*", iMock)).isTrue(); + softly.assertThat(rule.validate("abcdö", iMock)).isTrue(); + softly.assertThat(rule.validate("ab__cd", iMock)).isTrue(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isTrue(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateAtLeastLetterRule() { + ValidationRule rule = sut.createAtLeastLettersRule(4); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC", iMock)).isFalse(); + softly.assertThat(rule.validate("üäö", iMock)).isFalse(); + softly.assertThat(rule.validate("ಮಣೆ", iMock)).isFalse(); + softly.assertThat(rule.validate("1234", iMock)).isFalse(); + softly.assertThat(rule.validate("abc4", iMock)).isFalse(); + softly.assertThat(rule.validate("abc$", iMock)).isFalse(); + softly.assertThat(rule.validate("abc.", iMock)).isFalse(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isFalse(); + softly.assertThat(rule.validate("\\u0001\\u0001\\u0001", iMock)).isFalse(); + softly.assertThat(rule.validate("abcd", iMock)).isTrue(); + softly.assertThat(rule.validate("ABCD", iMock)).isTrue(); + softly.assertThat(rule.validate("üäöä", iMock)).isTrue(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateAtLeastLetterUppercaseRule() { + ValidationRule rule = sut.createAtLeastLettersUppercaseRule(4); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC", iMock)).isFalse(); + softly.assertThat(rule.validate("üäö", iMock)).isFalse(); + softly.assertThat(rule.validate("ಮಣೆ", iMock)).isFalse(); + softly.assertThat(rule.validate("1234", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC4", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC$", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC.", iMock)).isFalse(); + softly.assertThat(rule.validate("abcd", iMock)).isFalse(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isFalse(); + softly.assertThat(rule.validate("ABCD", iMock)).isTrue(); + softly.assertThat(rule.validate("üÜüÜüÜüÜ", iMock)).isTrue(); + softly.assertThat(rule.validate("КГБКГБ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateAtLeastLetterLowercaseRule() { + ValidationRule rule = sut.createAtLeastLettersLowercaseRule(4); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC", iMock)).isFalse(); + softly.assertThat(rule.validate("üäö", iMock)).isFalse(); + softly.assertThat(rule.validate("ಮಣೆ", iMock)).isFalse(); + softly.assertThat(rule.validate("1234", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC4", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC$", iMock)).isFalse(); + softly.assertThat(rule.validate("ABC.", iMock)).isFalse(); + softly.assertThat(rule.validate("ABCD", iMock)).isFalse(); + softly.assertThat(rule.validate("КГБКГБ", iMock)).isFalse(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isFalse(); + softly.assertThat(rule.validate("abcd", iMock)).isTrue(); + softly.assertThat(rule.validate("üÜüÜüÜüÜ", iMock)).isTrue(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateAtLeastDigitsRule() { + ValidationRule rule = sut.createAtLeastDigitsRule(4); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("abc123", iMock)).isFalse(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isFalse(); + softly.assertThat(rule.validate("1234", iMock)).isTrue(); + softly.assertThat(rule.validate("abc1234", iMock)).isTrue(); + softly.assertThat(rule.validate("a1b2c3d4e", iMock)).isTrue(); + softly.assertThat(rule.validate("1a2b3c4e5", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateAtLeastSpecalSignsRule() { + ValidationRule rule = sut.createAtLeastSpecialSignsRule(2); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("*", iMock)).isFalse(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("äöü", iMock)).isFalse(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isFalse(); + softly.assertThat(rule.validate("a+.", iMock)).isTrue(); + softly.assertThat(rule.validate("a+b£", iMock)).isTrue(); + softly.assertThat(rule.validate("a+b£c", iMock)).isTrue(); + softly.assertThat(rule.validate("!a+b£c", iMock)).isTrue(); + softly.assertThat(rule.validate("!a+b£c.", iMock)).isTrue(); + softly.assertThat(rule.validate("a$$$$$", iMock)).isTrue(); + softly.assertThat(rule.validate("12?^", iMock)).isTrue(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + // Should not be valid, but at least these passwords are invalid in LengthRule. + softly.assertThat(rule.validate("a d", iMock)).isTrue(); + softly.assertThat(rule.validate("\\u0001\\u0001\\u0001", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateAtLeastDigitsOrSpecalSignsRule() { + ValidationRule rule = sut.createAtLeastDigitsOrSpecialSignsRule(2); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("*", iMock)).isFalse(); + softly.assertThat(rule.validate("1", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("äöü", iMock)).isFalse(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isFalse(); + softly.assertThat(rule.validate("4§", iMock)).isTrue(); + softly.assertThat(rule.validate("a1/", iMock)).isTrue(); + softly.assertThat(rule.validate("a+.", iMock)).isTrue(); + softly.assertThat(rule.validate("a+b£", iMock)).isTrue(); + softly.assertThat(rule.validate("a1b£", iMock)).isTrue(); + softly.assertThat(rule.validate("a+b£", iMock)).isTrue(); + softly.assertThat(rule.validate("a+b£c2", iMock)).isTrue(); + softly.assertThat(rule.validate("!a2b£c", iMock)).isTrue(); + softly.assertThat(rule.validate("!a3b£c.", iMock)).isTrue(); + softly.assertThat(rule.validate("a$$$$$", iMock)).isTrue(); + softly.assertThat(rule.validate("12?^", iMock)).isTrue(); + // Should not be valid, but at least these passwords are invalid in LengthRule. + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + softly.assertThat(rule.validate("a d", iMock)).isTrue(); + softly.assertThat(rule.validate("\\u0001\\u0001\\u0001", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateLettersForbiddenRule() { + ValidationRule rule = sut.createLettersForbiddenRule(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("1c", iMock)).isFalse(); + softly.assertThat(rule.validate("abc", iMock)).isFalse(); + softly.assertThat(rule.validate("äöü", iMock)).isFalse(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isFalse(); + softly.assertThat(rule.validate("*", iMock)).isTrue(); + softly.assertThat(rule.validate("1", iMock)).isTrue(); + softly.assertThat(rule.validate("4§", iMock)).isTrue(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + softly.assertThat(rule.validate(" ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateLettersUppercaseForbiddenRule() { + ValidationRule rule = sut.createLettersUppercaseForbiddenRule(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("1C", iMock)).isFalse(); + softly.assertThat(rule.validate("aBc", iMock)).isFalse(); + softly.assertThat(rule.validate("äÖü", iMock)).isFalse(); + softly.assertThat(rule.validate("ГÑÌблонÑ", iMock)).isFalse(); + softly.assertThat(rule.validate("*", iMock)).isTrue(); + softly.assertThat(rule.validate("1", iMock)).isTrue(); + softly.assertThat(rule.validate("1c", iMock)).isTrue(); + softly.assertThat(rule.validate("4§", iMock)).isTrue(); + softly.assertThat(rule.validate("äü", iMock)).isTrue(); + softly.assertThat(rule.validate("abc", iMock)).isTrue(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + softly.assertThat(rule.validate(" ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateLettersLowercaseForbiddenRule() { + ValidationRule rule = sut.createLettersLowercaseForbiddenRule(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("1c", iMock)).isFalse(); + softly.assertThat(rule.validate("aBc", iMock)).isFalse(); + softly.assertThat(rule.validate("äÖü", iMock)).isFalse(); + softly.assertThat(rule.validate("ГÑÌблонÑ", iMock)).isFalse(); + softly.assertThat(rule.validate("*", iMock)).isTrue(); + softly.assertThat(rule.validate("1", iMock)).isTrue(); + softly.assertThat(rule.validate("1C", iMock)).isTrue(); + softly.assertThat(rule.validate("4§", iMock)).isTrue(); + softly.assertThat(rule.validate("ÖÜ", iMock)).isTrue(); + softly.assertThat(rule.validate("ABC", iMock)).isTrue(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + softly.assertThat(rule.validate(" ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateDigitsForbiddenRule() { + ValidationRule rule = sut.createDigitsForbiddenRule(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("1", iMock)).isFalse(); + softly.assertThat(rule.validate("1c", iMock)).isFalse(); + softly.assertThat(rule.validate("4§", iMock)).isFalse(); + softly.assertThat(rule.validate("123", iMock)).isFalse(); + softly.assertThat(rule.validate("abd", iMock)).isTrue(); + softly.assertThat(rule.validate("äöü", iMock)).isTrue(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isTrue(); + softly.assertThat(rule.validate("*", iMock)).isTrue(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isTrue(); + softly.assertThat(rule.validate(" ", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateSpecialSignsForbiddenRule() { + ValidationRule rule = sut.createSpecialSignsForbiddenRule(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("*", iMock)).isFalse(); + softly.assertThat(rule.validate("4%", iMock)).isFalse(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isFalse(); + softly.assertThat(rule.validate("a v", iMock)).isFalse(); + softly.assertThat(rule.validate("\\u0001cd", iMock)).isFalse(); + softly.assertThat(rule.validate("1c", iMock)).isTrue(); + softly.assertThat(rule.validate("aBc", iMock)).isTrue(); + softly.assertThat(rule.validate("äÖü", iMock)).isTrue(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isTrue(); + softly.assertThat(rule.validate("1", iMock)).isTrue(); + softly.assertThat(rule.validate("1C", iMock)).isTrue(); + softly.assertThat(rule.validate("ÖÜ", iMock)).isTrue(); + softly.assertThat(rule.validate("ABC", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldCreateDigitsAndSpecialSignsForbiddenRule() { + ValidationRule rule = sut.createDigitsAndSpecialSignsForbiddenRule(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("*", iMock)).isFalse(); + softly.assertThat(rule.validate("4%", iMock)).isFalse(); + softly.assertThat(rule.validate("😀😀😀😀", iMock)).isFalse(); + softly.assertThat(rule.validate("a v", iMock)).isFalse(); + softly.assertThat(rule.validate("\\u0001cd", iMock)).isFalse(); + softly.assertThat(rule.validate("1", iMock)).isFalse(); + softly.assertThat(rule.validate("1C", iMock)).isFalse(); + softly.assertThat(rule.validate("1c", iMock)).isFalse(); + softly.assertThat(rule.validate("aBc", iMock)).isTrue(); + softly.assertThat(rule.validate("äÖü", iMock)).isTrue(); + softly.assertThat(rule.validate("ÑÌблонÑ", iMock)).isTrue(); + softly.assertThat(rule.validate("ÖÜ", iMock)).isTrue(); + softly.assertThat(rule.validate("ABC", iMock)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldUsernameForbiddenRule() { + ValidationRule rule = sut.createUsernameForbiddenRule(); + + Identity identity = mock(Identity.class); + when(identity.getName()).thenReturn("myname"); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("myname", identity)).isFalse(); + softly.assertThat(rule.validate("MYNAME", identity)).isFalse(); + softly.assertThat(rule.validate("$$$MYNAME$$$", identity)).isFalse(); + softly.assertThat(rule.validate("myname01", identity)).isFalse(); + softly.assertThat(rule.validate("superman", identity)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldUserFirstnameForbiddenRule() { + ValidationRule rule = sut.createUserFirstnameForbiddenRule(); + + User user = mock(User.class); + when(user.getFirstName()).thenReturn("myname"); + Identity identity = mock(Identity.class); + when(identity.getUser()).thenReturn(user); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("myname", identity)).isFalse(); + softly.assertThat(rule.validate("MYNAME", identity)).isFalse(); + softly.assertThat(rule.validate("$$$MYNAME$$$", identity)).isFalse(); + softly.assertThat(rule.validate("myname01", identity)).isFalse(); + softly.assertThat(rule.validate("superman", identity)).isTrue(); + softly.assertAll(); + } + + @Test + public void shouldUserLastnameForbiddenRule() { + ValidationRule rule = sut.createUserLastnameForbiddenRule(); + + User user = mock(User.class); + when(user.getLastName()).thenReturn("myname"); + Identity identity = mock(Identity.class); + when(identity.getUser()).thenReturn(user); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(rule.validate("myname", identity)).isFalse(); + softly.assertThat(rule.validate("MYNAME", identity)).isFalse(); + softly.assertThat(rule.validate("$$$MYNAME$$$", identity)).isFalse(); + softly.assertThat(rule.validate("myname01", identity)).isFalse(); + softly.assertThat(rule.validate("superman", identity)).isTrue(); + softly.assertAll(); + } + + + + private static class TestableValidationRuleFactory extends PasswordValidationRuleFactory { + + @Override + protected Translator createTranslator() { + return mock(Translator.class); + } + + } + +} diff --git a/src/test/java/org/olat/login/validation/TestingRuleProvider.java b/src/test/java/org/olat/login/validation/TestingRuleProvider.java new file mode 100644 index 00000000000..1f6fffb31af --- /dev/null +++ b/src/test/java/org/olat/login/validation/TestingRuleProvider.java @@ -0,0 +1,61 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.login.validation; + +import java.util.ArrayList; +import java.util.List; + +import org.olat.login.validation.ValidationRule; +import org.olat.login.validation.ValidationRulesProvider; + + +/** + * + * Initial date: 13 May 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +class TestingRuleProvider implements ValidationRulesProvider { + + private List<ValidationRule> rules; + + static TestingRuleProvider of(ValidationRule rule) { + List<ValidationRule> rules = new ArrayList<>(1); + rules.add(rule); + return new TestingRuleProvider(rules); + } + + static TestingRuleProvider of(ValidationRule rule1, ValidationRule rule2) { + List<ValidationRule> rules = new ArrayList<>(2); + rules.add(rule1); + rules.add(rule2); + return new TestingRuleProvider(rules); + } + + private TestingRuleProvider(List<ValidationRule> rules) { + this.rules = rules; + } + + @Override + public List<ValidationRule> getRules() { + return rules; + } + +} diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 1c0aa676ef1..878bc08527b 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -149,7 +149,6 @@ import org.junit.runners.Suite; org.olat.basesecurity.BaseSecurityManagerTest.class, org.olat.user.UserDAOTest.class, org.olat.user.UserManagerTest.class, - org.olat.user.UserNameAndPasswordSyntaxCheckerWithRegexpTest.class, org.olat.user.manager.UserDataExportDAOTest.class, org.olat.user.manager.UserDataExportServiceTest.class, org.olat.repository.manager.AutomaticLifecycleServiceTest.class, @@ -448,6 +447,8 @@ import org.junit.runners.Suite; org.olat.core.gui.components.form.flexible.impl.elements.richText.TextModeTest.class, org.olat.core.gui.components.form.flexible.impl.elements.SelectboxSelectionImplTest.class, org.olat.core.gui.components.form.flexible.impl.elements.TextElementRendererTest.class, + org.olat.login.validation.PasswordSyntaxValidatorTest.class, + org.olat.login.validation.PasswordValidationRuleFactoryTest.class, org.olat.modules.card2brain.manager.Card2BrainManagerImplTest.class, org.olat.modules.edubase.manager.EdubaseManagerImplTest.class, org.olat.modules.edusharing.manager.EdusharingHtmlServiceImplTest.class, diff --git a/src/test/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexpTest.java b/src/test/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexpTest.java deleted file mode 100644 index 6f821f2b2b0..00000000000 --- a/src/test/java/org/olat/user/UserNameAndPasswordSyntaxCheckerWithRegexpTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.user; - -import org.junit.Assert; -import org.junit.Test; - -/** - * - * Initial date: 23.08.2013<br> - * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com - * - */ -public class UserNameAndPasswordSyntaxCheckerWithRegexpTest { - - @Test - public void defaultPasswordCheck() { - UserNameAndPasswordSyntaxCheckerWithRegexp checker = new UserNameAndPasswordSyntaxCheckerWithRegexp(); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kan")); - Assert.assertTrue(checker.syntaxCheckOlatPassword("Kanu#01")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kan\u00FC#01")); - } - - /** - * Min. 7 characters, one uppercase, one lowercase, one number - */ - @Test - public void customPasswordCheck_upperLowerCase_number() { - UserNameAndPasswordSyntaxCheckerWithRegexp checker = new UserNameAndPasswordSyntaxCheckerWithRegexp(); - checker.setPasswordRegExp("(?=^.{7,}$)((?=.*\\d)|(?=.*\\W+))(?![.\\n])(?=.*[A-Z])(?=.*[a-z]).*$"); - - Assert.assertTrue(checker.syntaxCheckOlatPassword("Kanu#01")); - Assert.assertTrue(checker.syntaxCheckOlatPassword("Kanuunc1")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanu#1"));//less than 7 characters - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanuunch"));//no number Kan\u00FC - Assert.assertTrue(checker.syntaxCheckOlatPassword("Kan\u00FCunc1"));// Umlaut allowed - } - - /** - * Min. 8 characters, one uppercase, one lowercase, one number, one special character - */ - @Test - public void customPasswordCheck_upperLowerCase_number_special() { - UserNameAndPasswordSyntaxCheckerWithRegexp checker = new UserNameAndPasswordSyntaxCheckerWithRegexp(); - checker.setPasswordRegExp("(?=^.{8,}$)((?=.*\\d)|(?=.*\\W+))(?![.\\n])(?=.*[A-Z])(?=.*[a-z])(?=.*[$@$!%*#?&]).*$"); - - Assert.assertTrue(checker.syntaxCheckOlatPassword("Kanu#010")); - Assert.assertTrue(checker.syntaxCheckOlatPassword("?Ryomou#010")); - Assert.assertTrue(checker.syntaxCheckOlatPassword("?Ryo ou#010")); - - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanuunc1")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanu#10"));//less than 8 characters - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanuunch"));//no number - Assert.assertFalse(checker.syntaxCheckOlatPassword("kanu8#10")); - } - - /** - * Min. 12 characters, at least one uppercase, one lowercase, one number and only - * alphanumeric characters allowed (no space, no underscore, no Umlaut) - */ - @Test - public void customPasswordCheck_upperLowerCase_number_noUmlaut() { - UserNameAndPasswordSyntaxCheckerWithRegexp checker = new UserNameAndPasswordSyntaxCheckerWithRegexp(); - checker.setPasswordRegExp("(?=^.{12,}$)(?=^[a-zA-Z0-9]+$)(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z]).*$"); - - Assert.assertTrue(checker.syntaxCheckOlatPassword("Kanu1asdfghj")); - Assert.assertTrue(checker.syntaxCheckOlatPassword("KASD123DFGHJj")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanuhasdfghj")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("kanu1asdfghj")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("kanugasdfghj")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanu1as fghj")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kanu1as_fghj")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("kanugasdfgh")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("JAHDFKL1DFSGJHG")); - Assert.assertFalse(checker.syntaxCheckOlatPassword("Kan\u00E41asdfghj")); - } - - -} -- GitLab