You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by jl...@apache.org on 2013/04/06 06:54:15 UTC

svn commit: r1465185 - in /ofbiz/trunk: applications/party/script/org/ofbiz/party/user/ framework/common/config/ framework/common/src/org/ofbiz/common/login/ framework/webapp/src/org/ofbiz/webapp/control/

Author: jleroux
Date: Sat Apr  6 04:54:14 2013
New Revision: 1465185

URL: http://svn.apache.org/r1465185
Log:
A slightly modified patch from Sumit Pandit for "Enforce user to reset his password in a pre-defined regular interval of time." https://issues.apache.org/jira/browse/OFBIZ-5009

Reference requirement for the feature: http://markmail.org/message/sihxekwk6655t5gh#query:+page:1+mid:bcw2vva2hjxhsodq+state:results

For a user account in system, we can set password age for an additional security.
Proposed system will start suggesting to user to reset his password few days before password expiration. Then Once password expired, system will enforce him to reset his password before processing further.
Following will be control points and would be part of system configuration- 
* *Control Points -*
** Admin can enable/disable the reset password functionality.
*** -It will control by a flag in propriety file where admin can enable/disable it by setting true/false.
** Number of days in which password will expired.
*** - It will defined in propriety file so that admin can control it.
** Number of days before when password expiration alert display at user's screen.
*** - It will defined in propriety file so that admin can control it.

* *How should it processed -*
** After user logged-in, display password expiration notification message to user if his password will expire in comming days.
** After user logged-in, display change password screen, when password is expired. i.e. The difference in days since last time password updated is exceed to number of days specified in system policies. Enforce user to reset his password.

* *What will be the out-put -*
** Password is about to expire : : alert message after login.
** Password is expired : Password-Expired-Alert : alert message with reset password screen.

Following is implementation plan -

    security.properties : Provide configuration for following control points :
        Enabling / Disabling of the functionality.
        Maximum number of days within user has to change the password.
        Number of days back to password expire date, when user start getting password expiration alerts.

    Data model
        Entity name : UserLoginPasswordHistory : Existing entity.

    Business logic
        Create UserLoginPasswordHistory record when a new user is created (if configured).
        Expire and then Create UserLoginPasswordHistory record when user update existing password.
        Everytime, when user login check for password expiration. If password expired then display change password screen to user. And if password not yet expired but it is close to expire display alert message to user about its expiration.

jleroux: I just changed 
from 
if (reqToChangePwdInDays != 0) {
tp
if (reqToChangePwdInDays > 0) {

Modified:
    ofbiz/trunk/applications/party/script/org/ofbiz/party/user/UserEvents.xml
    ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml
    ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java

Modified: ofbiz/trunk/applications/party/script/org/ofbiz/party/user/UserEvents.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/script/org/ofbiz/party/user/UserEvents.xml?rev=1465185&r1=1465184&r2=1465185&view=diff
==============================================================================
--- ofbiz/trunk/applications/party/script/org/ofbiz/party/user/UserEvents.xml (original)
+++ ofbiz/trunk/applications/party/script/org/ofbiz/party/user/UserEvents.xml Sat Apr  6 04:54:14 2013
@@ -320,6 +320,20 @@ under the License.
             <set field="newUserLogin.partyId" from-field="tempMap.partyId"/>
             <create-value value-field="newUserLogin"/>
             <set-current-user-login value-field="newUserLogin"/>
+            
+            <!-- On successful user creation, create password history record if configured -->
+            <set field="delegator" from-field="parameters.delegator" type="Object"/>
+            <call-class-method method-name="getPropertyValue" class-name="org.ofbiz.base.util.UtilProperties" ret-field="autoPasswordChangeEnabled">
+                <string value="security"/>
+                <string value="user.auto.change.password.enable"/>
+            </call-class-method>
+            <if-compare-field field="autoPasswordChangeEnabled" operator="equals" to-field="true">
+                <call-class-method method-name="createUserLoginPasswordHistory" class-name="org.ofbiz.common.login.LoginServices">
+                    <field field="delegator" type="org.ofbiz.entity.Delegator"/>
+                    <string value="${newUserLogin.userLoginId}"/>
+                    <string value="${newUserLogin.currentPassword}"/>
+                </call-class-method>
+            </if-compare-field>
         </if-not-empty>
 
         <create-value value-field="partyDataSource"/>

Modified: ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml?rev=1465185&r1=1465184&r2=1465185&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml (original)
+++ ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml Sat Apr  6 04:54:14 2013
@@ -166,6 +166,12 @@
         <value xml:lang="zh">没有设置电子邮件地址,请与客户服务联系。</value>
         <value xml:lang="zh_TW">無電子郵件, 請與客服連絡。</value>
     </property>
+    <property key="loginevents.password_expiration_alert">
+        <value xml:lang="en">Alert : Your password will expire on ${passwordExpirationDate}. Update password before it expired.</value>
+    </property>
+    <property key="loginevents.password_expired_message">
+        <value xml:lang="en">Alert : Your password expired on ${passwordExpirationDate}. Update your password.</value>
+    </property>
     <property key="loginevents.password_hint_is">
         <value xml:lang="de">Der Passwort-Hinweis ist: ${passwordHint}.</value>
         <value xml:lang="en">The Password Hint is: ${passwordHint}.</value>

Modified: ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java?rev=1465185&r1=1465184&r2=1465185&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java (original)
+++ ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java Sat Apr  6 04:54:14 2013
@@ -422,7 +422,7 @@ public class LoginServices {
         return result;
     }
 
-    private static void createUserLoginPasswordHistory(Delegator delegator,String userLoginId, String currentPassword) throws GenericEntityException{
+    public static void createUserLoginPasswordHistory(Delegator delegator,String userLoginId, String currentPassword) throws GenericEntityException{
         int passwordChangeHistoryLimit = 0;
         try {
             passwordChangeHistoryLimit = Integer.parseInt(UtilProperties.getPropertyValue("security.properties", "password.change.history.limit", "0"));

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java?rev=1465185&r1=1465184&r2=1465185&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java Sat Apr  6 04:54:14 2013
@@ -22,6 +22,7 @@ import static org.ofbiz.base.util.UtilGe
 
 import java.math.BigInteger;
 import java.security.cert.X509Certificate;
+import java.sql.Timestamp;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
@@ -44,6 +45,7 @@ import org.ofbiz.base.util.GeneralExcept
 import org.ofbiz.base.util.KeyStoreUtil;
 import org.ofbiz.base.util.StringUtil;
 import org.ofbiz.base.util.StringUtil.StringWrapper;
+import org.ofbiz.base.util.UtilDateTime;
 import org.ofbiz.base.util.UtilFormatOut;
 import org.ofbiz.base.util.UtilHttp;
 import org.ofbiz.base.util.UtilMisc;
@@ -60,6 +62,7 @@ import org.ofbiz.entity.model.ModelEntit
 import org.ofbiz.entity.serialize.XmlSerializer;
 import org.ofbiz.entity.transaction.GenericTransactionException;
 import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.security.Security;
 import org.ofbiz.security.SecurityConfigurationException;
 import org.ofbiz.security.SecurityFactory;
@@ -451,6 +454,12 @@ public class LoginWorker {
             if (userLogin != null && "Y".equals(userLogin.getString("requirePasswordChange"))) {
                 return "requirePasswordChange";
             }
+            String autoChangePassword = UtilProperties.getPropertyValue("security.properties", "user.auto.change.password.enable", "false");
+            if ("true".equalsIgnoreCase(autoChangePassword)) {
+                if ("requirePasswordChange".equals(autoChangePassword(request, response))) {
+                    return "requirePasswordChange";
+                }
+            }
 
             // check on JavaScriptEnabled
             String javaScriptEnabled = "N";
@@ -1033,4 +1042,40 @@ public class LoginWorker {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
     }
 
+    public static String autoChangePassword(HttpServletRequest request, HttpServletResponse response) {
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
+        String userName = request.getParameter("USERNAME");
+        Timestamp now = UtilDateTime.nowTimestamp();
+        Integer reqToChangePwdInDays = Integer.valueOf(UtilProperties.getPropertyValue("security.properties", "user.change.password.days", "0"));
+        Integer passwordNoticePeriod = Integer.valueOf(UtilProperties.getPropertyValue("security.properties", "user.change.password.notification.days", "0"));
+        if (reqToChangePwdInDays > 0) {
+            List<GenericValue> passwordHistories = null;
+            try {
+                passwordHistories = delegator.findByAnd("UserLoginPasswordHistory", UtilMisc.toMap("userLoginId", userName));
+            } catch (GenericEntityException e) {
+                Debug.logError(e, "Cannot get user's password history record: " + e.getMessage(), module);
+            }
+            if (UtilValidate.isNotEmpty(passwordHistories)) {
+                GenericValue passwordHistory = EntityUtil.getFirst(EntityUtil.filterByDate(passwordHistories));
+                Timestamp passwordCreationDate = passwordHistory.getTimestamp("fromDate");
+                Integer passwordValidDays = reqToChangePwdInDays - passwordNoticePeriod; // Notification starts after days.
+                Timestamp startNotificationFromDate = UtilDateTime.addDaysToTimestamp(passwordCreationDate, passwordValidDays);
+                Timestamp passwordExpirationDate = UtilDateTime.addDaysToTimestamp(passwordCreationDate, reqToChangePwdInDays);
+                if (now.after(startNotificationFromDate)) {
+                    if (now.after(passwordExpirationDate)) {
+                        Map<String, String> messageMap = UtilMisc.toMap("passwordExpirationDate", passwordExpirationDate.toString());
+                        String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.password_expired_message", messageMap, UtilHttp.getLocale(request));
+                        request.setAttribute("_EVENT_MESSAGE_", errMsg);
+                        return "requirePasswordChange";
+                    } else {
+                        Map<String, String> messageMap = UtilMisc.toMap("passwordExpirationDate", passwordExpirationDate.toString());
+                        String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.password_expiration_alert", messageMap, UtilHttp.getLocale(request));
+                        request.setAttribute("_EVENT_MESSAGE_", errMsg);
+                        return "success";
+                    }
+                }
+            }
+        }
+        return "success";
+    }
 }