diff --git a/api/src/main/resources/messages.properties b/api/src/main/resources/messages.properties
index 8f21ed23..496086a9 100644
--- a/api/src/main/resources/messages.properties
+++ b/api/src/main/resources/messages.properties
@@ -16,6 +16,11 @@ adminui.noname=No Name
adminui.field.too.long=The value you entered is too long
adminui.field.exceeded.maxChars=A maximum of {0} character(s) is allowed
adminui.field.require.minChars=At least {0} character(s) are required
+adminui.field.require.pattern.begin=This password must have:
+adminui.field.require.pattern.reqUpperAndLowerCase=both upper and lowercase characters
+adminui.field.require.pattern.reqDigit=at least one digit
+adminui.field.require.pattern.reqNonDigit=at least one non digit
+adminui.field.require.pattern.reqRegex=match this Regex pattern: {0}
adminui.retire=Retire {0}?
adminui.purge=Delete {0} Forever?
adminui.requiredField.label=required
diff --git a/omod/src/main/java/org/openmrs/module/adminui/page/controller/PasswordValidation.java b/omod/src/main/java/org/openmrs/module/adminui/page/controller/PasswordValidation.java
new file mode 100644
index 00000000..cecd80b1
--- /dev/null
+++ b/omod/src/main/java/org/openmrs/module/adminui/page/controller/PasswordValidation.java
@@ -0,0 +1,63 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public License,
+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
+ * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
+ * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
+ *
+ * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
+ * graphic logo is a trademark of OpenMRS Inc.
+ */
+package org.openmrs.module.adminui.page.controller;
+
+import org.apache.commons.lang.StringUtils;
+import org.openmrs.api.AdministrationService;
+import org.openmrs.api.context.Context;
+import org.openmrs.messagesource.MessageSourceService;
+import org.openmrs.ui.framework.page.PageModel;
+import org.openmrs.util.OpenmrsConstants;
+
+public final class PasswordValidation {
+ private PasswordValidation() {
+
+ }
+
+ public static void addPasswordValidationAttributes(PageModel model, AdministrationService adminService, MessageSourceService mss) {
+ String passwordMinLength = adminService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_MINIMUM_LENGTH, "8");
+ boolean passwordReqUpperAndLowerCase = "true".equals(adminService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_REQUIRES_UPPER_AND_LOWER_CASE, "true"));
+ boolean passwordReqDigit = "true".equals(adminService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_REQUIRES_DIGIT, "true"));
+ boolean passwordReqNonDigit = "true".equals(adminService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_REQUIRES_NON_DIGIT, "true"));
+ String passwordReqRegex = adminService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_CUSTOM_REGEX, "");
+
+ String pattern = "";
+ String patternErrorMessage = "";
+
+ if (passwordReqUpperAndLowerCase || passwordReqDigit || passwordReqNonDigit || StringUtils.isNotEmpty(passwordReqRegex)) {
+ pattern += "/^";
+ patternErrorMessage += mss.getMessage("adminui.field.require.pattern.begin");
+ if (passwordReqUpperAndLowerCase) {
+ pattern += "(?=.*?[A-Z])(?=.*?[a-z])";
+ patternErrorMessage += ' ' + mss.getMessage("adminui.field.require.pattern.reqUpperAndLowerCase") + ',';
+ }
+ if (passwordReqDigit) {
+ pattern += "(?=.*\\d)";
+ patternErrorMessage += ' ' + mss.getMessage("adminui.field.require.pattern.reqDigit") + ',';
+ }
+ if (passwordReqNonDigit) {
+ pattern += "(?=.*[^\\d])";
+ patternErrorMessage += ' ' + mss.getMessage("adminui.field.require.pattern.reqNonDigit") + ',';
+ }
+ if (StringUtils.isNotEmpty(passwordReqRegex)) {
+ pattern += "(?=";
+ pattern += passwordReqRegex;
+ pattern += ')';
+ patternErrorMessage += ' ' + mss.getMessage("adminui.field.require.pattern.reqRegex", new Object[]{passwordReqRegex}, Context.getLocale()) + ',';
+ }
+ pattern += "[\\w|\\W]*$/";
+ patternErrorMessage = patternErrorMessage.substring(0, patternErrorMessage.length() - 1);
+ }
+
+ model.addAttribute("passwordMinLength", passwordMinLength);
+ model.addAttribute("pattern", pattern);
+ model.addAttribute("patternErrorMessage", patternErrorMessage);
+ }
+}
diff --git a/omod/src/main/java/org/openmrs/module/adminui/page/controller/myaccount/ChangePasswordPageController.java b/omod/src/main/java/org/openmrs/module/adminui/page/controller/myaccount/ChangePasswordPageController.java
index ae6a2b5d..5d1ca069 100644
--- a/omod/src/main/java/org/openmrs/module/adminui/page/controller/myaccount/ChangePasswordPageController.java
+++ b/omod/src/main/java/org/openmrs/module/adminui/page/controller/myaccount/ChangePasswordPageController.java
@@ -23,6 +23,7 @@
import org.openmrs.api.context.Context;
import org.openmrs.api.db.DAOException;
import org.openmrs.messagesource.MessageSourceService;
+import org.openmrs.module.adminui.page.controller.PasswordValidation;
import org.openmrs.module.uicommons.UiCommonsConstants;
import org.openmrs.module.uicommons.util.InfoErrorMessageUtil;
import org.openmrs.ui.framework.annotation.SpringBean;
@@ -48,13 +49,14 @@ public String overridePostChangePassword() {
return "forward:/adminui/myaccount/changePassword.page";
}
- public void get(PageModel model, @SpringBean("adminService") AdministrationService adminService) {
- setModelAttributes(model, adminService);
+ public void get(PageModel model,
+ @SpringBean("adminService") AdministrationService adminService,
+ @SpringBean("messageSourceService") MessageSourceService mss) {
+ setModelAttributes(model, adminService, mss);
}
- public void setModelAttributes(PageModel model, AdministrationService adminService) {
- model.addAttribute("passwordMinLength",
- adminService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_MINIMUM_LENGTH, "8"));
+ public void setModelAttributes(PageModel model, AdministrationService adminService, MessageSourceService mss) {
+ PasswordValidation.addPasswordValidationAttributes(model, adminService, mss);
}
public String post(PageModel model, @SpringBean("userService") UserService userService,
@@ -77,7 +79,7 @@ public String post(PageModel model, @SpringBean("userService") UserService userS
if (errorMessage == null) {
try {
OpenmrsUtil.validatePassword(user.getUsername(), newPassword, user.getSystemId());
-
+
String nextPage = "redirect:/index.htm";
try {
userService.changePassword(oldPassword, newPassword);
@@ -132,7 +134,7 @@ public String post(PageModel model, @SpringBean("userService") UserService userS
request.getSession().setAttribute(UiCommonsConstants.SESSION_ATTRIBUTE_ERROR_MESSAGE, errorMessage);
- setModelAttributes(model, adminService);
+ setModelAttributes(model, adminService, mss);
return "myaccount/changePassword";
}
diff --git a/omod/src/main/java/org/openmrs/module/adminui/page/controller/systemadmin/accounts/AccountPageController.java b/omod/src/main/java/org/openmrs/module/adminui/page/controller/systemadmin/accounts/AccountPageController.java
index 0784f99b..4c5abcec 100644
--- a/omod/src/main/java/org/openmrs/module/adminui/page/controller/systemadmin/accounts/AccountPageController.java
+++ b/omod/src/main/java/org/openmrs/module/adminui/page/controller/systemadmin/accounts/AccountPageController.java
@@ -35,6 +35,7 @@
import org.openmrs.module.adminui.account.Account;
import org.openmrs.module.adminui.account.AccountService;
import org.openmrs.module.adminui.account.AdminUiAccountValidator;
+import org.openmrs.module.adminui.page.controller.PasswordValidation;
import org.openmrs.module.appframework.domain.Extension;
import org.openmrs.module.appframework.service.AppFrameworkService;
import org.openmrs.module.providermanagement.Provider;
@@ -88,12 +89,13 @@ public Account getAccount(@RequestParam(value = "personId", required = false) Pe
public void get(PageModel model, @MethodParam("getAccount") Account account,
@SpringBean("adminAccountService") AccountService accountService,
@SpringBean("adminService") AdministrationService administrationService,
+ @SpringBean("messageSourceService") MessageSourceService mss,
@SpringBean("providerManagementService") ProviderManagementService providerManagementService,
UiUtils uu,
@SpringBean("appFrameworkService") AppFrameworkService appFrameworkService)
throws IOException {
- setModelAttributes(model, account, null, accountService, administrationService, providerManagementService, uu, appFrameworkService);
+ setModelAttributes(model, account, null, accountService, administrationService, mss, providerManagementService, uu, appFrameworkService);
if (account.getPerson().getPersonId() == null) {
setJsonFormData(model, account, null);
}
@@ -115,6 +117,7 @@ public String post(PageModel model, @MethodParam("getAccount") @BindParams Accou
@SpringBean("messageSourceService") MessageSourceService messageSourceService,
@SpringBean("adminAccountService") AccountService accountService,
@SpringBean("adminService") AdministrationService administrationService,
+ @SpringBean("messageSourceService") MessageSourceService mss,
@SpringBean("adminUiAccountValidator") AdminUiAccountValidator accountValidator,
@SpringBean("providerManagementService") ProviderManagementService providerManagementService,
@SpringBean("appFrameworkService") AppFrameworkService appFrameworkService,
@@ -211,7 +214,7 @@ public String post(PageModel model, @MethodParam("getAccount") @BindParams Accou
}
}
- setModelAttributes(model, account, otherAccountData, accountService, administrationService,
+ setModelAttributes(model, account, otherAccountData, accountService, administrationService, mss,
providerManagementService, uu, appFrameworkService);
sendErrorMessage(errors, model, messageSourceService, request);
@@ -226,8 +229,8 @@ public String post(PageModel model, @MethodParam("getAccount") @BindParams Accou
public void setModelAttributes(PageModel model, Account account, OtherAccountData otherAccountData,
AccountService accountService, AdministrationService administrationService,
- ProviderManagementService providerManagementService, UiUtils uu,
- AppFrameworkService appFrameworkService) throws IOException {
+ MessageSourceService mss, ProviderManagementService providerManagementService,
+ UiUtils uu, AppFrameworkService appFrameworkService) throws IOException {
model.addAttribute("account", account);
Boolean forcePasswordChange = null;
@@ -284,8 +287,7 @@ public void setModelAttributes(PageModel model, Account account, OtherAccountDat
propertyMaxLengthMap.put("username", administrationService.getMaximumPropertyLength(User.class, "username"));
propertyMaxLengthMap.put("password", administrationService.getMaximumPropertyLength(User.class, "password"));
model.addAttribute("propertyMaxLengthMap", propertyMaxLengthMap);
- model.addAttribute("passwordMinLength",
- administrationService.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_MINIMUM_LENGTH, "8"));
+ PasswordValidation.addPasswordValidationAttributes(model, administrationService, mss);
ObjectMapper mapper = new ObjectMapper();
SimpleObject so = new SimpleObject();
diff --git a/omod/src/main/webapp/fragments/systemadmin/accounts/userFormFields.gsp b/omod/src/main/webapp/fragments/systemadmin/accounts/userFormFields.gsp
index 91b6aff9..50dccf77 100644
--- a/omod/src/main/webapp/fragments/systemadmin/accounts/userFormFields.gsp
+++ b/omod/src/main/webapp/fragments/systemadmin/accounts/userFormFields.gsp
@@ -42,6 +42,10 @@
passwordAttributes[requiredAttribute] = requiredAttributeValue;
}
+ if (pattern) {
+ passwordAttributes.put("ng-pattern", pattern);
+ }
+
def otherPasswordAttributes= ["ng-model": "uuidUserMap['"+userUuid+"'].password"]
otherPasswordAttributes.putAll(passwordAttributes)
%>
@@ -104,8 +108,13 @@
${ui.message("adminui.field.required")}
- ${ui.message("adminui.field.require.minChars", passwordMinLength)}
+ ${ui.message("adminui.field.require.minChars", passwordMinLength)}
+
+ <% if (pattern) { %>
+
+ ${patternErrorMessage}
+ <% } %>