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 2015/11/27 21:37:15 UTC

svn commit: r1716915 - in /ofbiz/trunk: applications/party/script/org/ofbiz/party/user/ applications/party/widget/partymgr/ applications/securityext/config/ applications/securityext/email/default/ applications/securityext/src/org/ofbiz/securityext/logi...

Author: jleroux
Date: Fri Nov 27 20:37:15 2015
New Revision: 1716915

URL: http://svn.apache.org/viewvc?rev=1716915&view=rev
Log:
A modified patch from Harsha Chadhar for "New feature to reclaim a user account - Using Security Questions" https://issues.apache.org/jira/browse/OFBIZ-4983

jleroux: the issue description is quite lengthy so I will summarise it here, please refer to the Jira issue for details.
"When a customer creates an account on eCommerce site, s/he will also need to answer a security question. This security question then can be used to reclaim the customer account in case s/he forgets her password. If the user correctly answers the required security question while reclaiming his account, her/his password will be sent through email notification. This part would work in the same way as the existing functionality of email password (forget password)."

The description was actually more ambitious (several questions, possibility for users to create own questions) but AFAIK these parts have not been implemented.

Apart updating the patch which did not merge, I got 2 majors issues (and few others I will not report here) I bypassed with workarounds
Unlike Harsha, and as I reported earlier in the issue, I never got the username (userLoginId) back when using hidden parameters in the request body (not in requestParameters, ie UtilHttp.getParameterMap(request)), nor actually any parameters. This is maybe due to my OS (Windows7 was XP before) or my email client (Outlook Express then, now Thunderbird) or even my SMTP configuration (I used my ISP SMTP server) but most probably because I did it all on my sole machine (localhost). I tried to understand what was happening to request body parameters with http://www.telerik.com/fiddler, but I finally gave up because it's even more complicated when https is in the picture. So I decided to rather use parameters in the URL (Query string). It's a bit less safe, though the password is OFBiz encrypted, and should be replaced. But it's safe enough because only the user should receive this message and it even if the message is sniffed during its journey it should be hard to decrypt the password!

Harsha used the SecurityExtUiLabels.xml (created by ashish at r1618415) in securityext component but there is already a SecurityextUiLabels.xml in common component. Since I use Windows OFBiz was unable to retrieve the labels from SecurityExtUiLabels.xml since I guess it looked into a SecurityextUiLabels.xml. So I renamed a SecurityExtUiLabels.xml to EmailPassword.xml.









Added:
    ofbiz/trunk/applications/securityext/config/EmailPassword.xml
      - copied, changed from r1716376, ofbiz/trunk/applications/securityext/config/SecurityExtUiLabels.xml
    ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl   (with props)
    ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml   (with props)
Removed:
    ofbiz/trunk/applications/securityext/config/SecurityExtUiLabels.xml
Modified:
    ofbiz/trunk/applications/party/script/org/ofbiz/party/user/UserEvents.xml
    ofbiz/trunk/applications/party/widget/partymgr/PartyForms.xml
    ofbiz/trunk/applications/securityext/email/default/passwordemail.ftl
    ofbiz/trunk/applications/securityext/src/org/ofbiz/securityext/login/LoginEvents.java
    ofbiz/trunk/applications/securityext/widget/EmailSecurityScreens.xml
    ofbiz/trunk/framework/common/config/SecurityUiLabels.xml
    ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml
    ofbiz/trunk/framework/common/servicedef/services.xml
    ofbiz/trunk/framework/common/servicedef/services_security.xml
    ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java
    ofbiz/trunk/framework/common/webcommon/WEB-INF/common-controller.xml
    ofbiz/trunk/framework/common/webcommon/changePassword.ftl
    ofbiz/trunk/framework/common/webcommon/forgotPassword.ftl
    ofbiz/trunk/framework/common/webcommon/login.ftl
    ofbiz/trunk/framework/common/widget/CommonScreens.xml
    ofbiz/trunk/framework/common/widget/SecurityForms.xml
    ofbiz/trunk/framework/security/config/security.properties
    ofbiz/trunk/framework/security/entitydef/entitymodel.xml
    ofbiz/trunk/framework/security/ofbiz-component.xml
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java
    ofbiz/trunk/specialpurpose/ecommerce/script/org/ofbiz/ecommerce/customer/CustomerEvents.xml

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=1716915&r1=1716914&r2=1716915&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 Fri Nov 27 20:37:15 2015
@@ -419,6 +419,13 @@ under the License.
         <set field="createProductStoreRoleMap.productStoreId" from-field="parameters.PRODUCT_STORE_ID"/>
         <call-service service-name="createProductStoreRole" in-map-name="createProductStoreRoleMap"/>
 
+        <if-not-empty field="parameters.securityAnswer">
+            <set field="createULSQContext.userLoginId" from-field="parameters.USERNAME"/>
+            <set field="createULSQContext.questionEnumId" from-field="parameters.securityQuestion"/>
+            <set field="createULSQContext.securityAnswer" from-field="parameters.securityAnswer"/>
+            <call-service service-name="createUserLoginSecurityQuestion" in-map-name="createULSQContext" />
+        </if-not-empty>
+
         <!--send New User Email Notification-->
         <set field="emailContext.partyId" from-field="partyId"/>
         <set field="emailContext.productStoreId" from-field="parameters.PRODUCT_STORE_ID"/>

Modified: ofbiz/trunk/applications/party/widget/partymgr/PartyForms.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/widget/partymgr/PartyForms.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/applications/party/widget/partymgr/PartyForms.xml (original)
+++ ofbiz/trunk/applications/party/widget/partymgr/PartyForms.xml Fri Nov 27 20:37:15 2015
@@ -652,7 +652,16 @@ under the License.
         <field name="USERNAME" title="${uiLabelMap.CommonUsername}" tooltip="* ${uiLabelMap.PartyTemporaryPassword}" required-field="true"><text size="30" maxlength="250"/></field>
         <!--<field name="RequiredNote" title=" "><display description="${uiLabelMap.PartyRequiredNote}" also-hidden="false"/></field> -->
 
-        <field name="PRODUCT_STORE_ID" title="Product Store" required-field="true">
+        <field name="securityQuestion">
+          <drop-down allow-empty="true">
+              <entity-options entity-name="Enumeration" key-field-name="enumId" description="${description}">
+                 <entity-constraint name="enumTypeId" operator="equals" value="SQ_STANDARD" /> 
+              </entity-options>
+          </drop-down>
+        </field>
+        <field name="securityAnswer" title="${uiLabelMap.SecurityAnswer}"><text /></field>
+
+        <field name="PRODUCT_STORE_ID" title="Product Store" tooltip="${uiLabelMap.CommonRequired}" widget-style="required">
             <drop-down>
                 <entity-options entity-name="ProductStore" key-field-name="productStoreId" description="${storeName} (${productStoreId})">
                     <entity-order-by field-name="productStoreId"/>

Copied: ofbiz/trunk/applications/securityext/config/EmailPassword.xml (from r1716376, ofbiz/trunk/applications/securityext/config/SecurityExtUiLabels.xml)
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/securityext/config/EmailPassword.xml?p2=ofbiz/trunk/applications/securityext/config/EmailPassword.xml&p1=ofbiz/trunk/applications/securityext/config/SecurityExtUiLabels.xml&r1=1716376&r2=1716915&rev=1716915&view=diff
==============================================================================
--- ofbiz/trunk/applications/securityext/config/SecurityExtUiLabels.xml (original)
+++ ofbiz/trunk/applications/securityext/config/EmailPassword.xml Fri Nov 27 20:37:15 2015
@@ -23,7 +23,7 @@
         <value xml:lang="da">en ny</value>
         <value xml:lang="de">Ein neues</value>
         <value xml:lang="en">a new</value>
-        <value xml:lang="fr">un nouvel</value>
+        <value xml:lang="fr">un nouveau</value>
         <value xml:lang="it">una nuova</value>
         <value xml:lang="ja">お知らせ</value>
         <value xml:lang="nl">een nieuw(e)</value>
@@ -63,7 +63,7 @@
         <value xml:lang="da">kodeord er sendt til Dem</value>
         <value xml:lang="de">Passwort das Ihnen zugesendet wurde</value>
         <value xml:lang="en">password sent to you</value>
-        <value xml:lang="fr">mot de passe qui vous a été envoyé</value>
+        <value xml:lang="fr">mot de passe</value>
         <value xml:lang="it">password inviata a te</value>
         <value xml:lang="ja">パスワードを送信しました</value>
         <value xml:lang="nl">Wachtwoord dat naar u verzonden is</value>

Modified: ofbiz/trunk/applications/securityext/email/default/passwordemail.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/securityext/email/default/passwordemail.ftl?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/applications/securityext/email/default/passwordemail.ftl (original)
+++ ofbiz/trunk/applications/securityext/email/default/passwordemail.ftl Fri Nov 27 20:37:15 2015
@@ -24,12 +24,14 @@ under the License.
   <div>${uiLabelMap.SecurityExtThisEmailIsInResponseToYourRequestToHave} <#if useEncryption>${uiLabelMap.SecurityExtANew}<#else>${uiLabelMap.SecurityExtYour}</#if> ${uiLabelMap.SecurityExtPasswordSentToYou}.</div>
   <br />
   <div>
-      <#if useEncryption>
-          ${uiLabelMap.SecurityExtNewPasswordMssgEncryptionOn}
-      <#else>
-          ${uiLabelMap.SecurityExtNewPasswordMssgEncryptionOff}
-      </#if>
-      "${password}"
+      <form method="post" action="${baseEcommerceSecureUrl}/partymgr/control/passwordChange?USERNAME=${userLogin.userLoginId!}&password=${password!}&forgotPwdFlag=true&tenantId=${tenantId!}" name="loginform" id="loginform" target="_blank">
+      <#--form method="post" action="${baseEcommerceSecureUrl}/partymgr/control/passwordChange" name="loginform" id="loginform" target="_blank">
+        <input type="hidden" name="USERNAME" value="${userLogin.userLoginId!}" />
+        <input type="hidden"  name="password" value="${password!}" />
+        <input type="hidden"  name="tenantId" value="${tenantId!}" />
+        <input type="hidden" name="forgotPwdFlag" value="true" /--><#-- see OFBIZ-4983 -->
+        <input type="submit" name="submit" value="${uiLabelMap.ResetPassword}" />
+      </form>
   </div>
 </body>
 </html>

Modified: ofbiz/trunk/applications/securityext/src/org/ofbiz/securityext/login/LoginEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/securityext/src/org/ofbiz/securityext/login/LoginEvents.java?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/applications/securityext/src/org/ofbiz/securityext/login/LoginEvents.java (original)
+++ ofbiz/trunk/applications/securityext/src/org/ofbiz/securityext/login/LoginEvents.java Fri Nov 27 20:37:15 2015
@@ -29,7 +29,9 @@ import javax.servlet.http.HttpServletRes
 import javax.servlet.http.HttpSession;
 
 import org.apache.commons.lang.RandomStringUtils;
+import org.ofbiz.base.crypto.HashCrypt;
 import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.GeneralException;
 import org.ofbiz.base.util.UtilFormatOut;
 import org.ofbiz.base.util.UtilHttp;
 import org.ofbiz.base.util.UtilMisc;
@@ -37,10 +39,11 @@ import org.ofbiz.base.util.UtilPropertie
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.string.FlexibleStringExpander;
 import org.ofbiz.common.login.LoginServices;
-import org.ofbiz.base.crypto.HashCrypt;
 import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericDelegator;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.util.EntityCrypto;
 import org.ofbiz.entity.util.EntityQuery;
 import org.ofbiz.entity.util.EntityUtilProperties;
 import org.ofbiz.party.contact.ContactHelper;
@@ -59,7 +62,7 @@ public class LoginEvents {
     public static final String module = LoginEvents.class.getName();
     public static final String resource = "SecurityextUiLabels";
     public static final String usernameCookieName = "OFBiz.Username";
-
+    private static final String keyValue = UtilProperties.getPropertyValue(LoginWorker.securityProperties, "login.secret_key_string");
     /**
      * Save USERNAME and PASSWORD for use by auth pages even if we start in non-auth pages.
      *
@@ -107,6 +110,31 @@ public class LoginEvents {
      * @return String specifying the exit status of this event
      */
     public static String forgotPassword(HttpServletRequest request, HttpServletResponse response) {
+        GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
+        String questionEnumId = request.getParameter("securityQuestion");
+        String securityAnswer = request.getParameter("securityAnswer");
+        String userLoginId = request.getParameter("USERNAME");
+        String errMsg = null;
+
+        try {
+            GenericValue userLoginSecurityQuestion = delegator.findOne("UserLoginSecurityQuestion", UtilMisc.toMap("questionEnumId", questionEnumId, "userLoginId", userLoginId), true);
+            if (UtilValidate.isNotEmpty(userLoginSecurityQuestion)) {
+                if (UtilValidate.isEmpty(securityAnswer)) {
+                    errMsg = UtilProperties.getMessage(resource, "loginservices.security_answer_empty", UtilHttp.getLocale(request));
+                    request.setAttribute("_ERROR_MESSAGE_", errMsg);
+                    return "error";
+                }
+                String ulSecurityAnswer = userLoginSecurityQuestion.getString("securityAnswer");
+                if (UtilValidate.isNotEmpty(ulSecurityAnswer) && !securityAnswer.equalsIgnoreCase(ulSecurityAnswer)) {
+                    errMsg = UtilProperties.getMessage(resource, "loginservices.security_answer_not_match", UtilHttp.getLocale(request));
+                    request.setAttribute("_ERROR_MESSAGE_", errMsg);
+                    return "error";
+                }
+            }
+        } catch (GenericEntityException e) {
+            errMsg = UtilProperties.getMessage(resource, "loginevents.problem_getting_security_question_record", UtilHttp.getLocale(request));
+            Debug.logError(e, errMsg, module);
+        }
         if ((UtilValidate.isNotEmpty(request.getParameter("GET_PASSWORD_HINT"))) || (UtilValidate.isNotEmpty(request.getParameter("GET_PASSWORD_HINT.x")))) {
             return showPasswordHint(request, response);
         } else if ((UtilValidate.isNotEmpty(request.getParameter("EMAIL_PASSWORD"))) || (UtilValidate.isNotEmpty(request.getParameter("EMAIL_PASSWORD.x")))) {
@@ -200,7 +228,7 @@ public class LoginEvents {
 
         GenericValue supposedUserLogin = null;
         String passwordToSend = null;
-
+        String autoPassword = null;
         try {
             supposedUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne();
             if (supposedUserLogin == null) {
@@ -215,7 +243,14 @@ public class LoginEvents {
                 if ("true".equals(EntityUtilProperties.getPropertyValue("security", "password.lowercase", delegator))){
                     passwordToSend=passwordToSend.toLowerCase();
                 }
-                supposedUserLogin.set("currentPassword", HashCrypt.cryptUTF8(LoginServices.getHashType(), null, passwordToSend));
+                autoPassword = RandomStringUtils.randomAlphanumeric(Integer.parseInt(EntityUtilProperties.getPropertyValue("security", "password.length.min", "5", delegator)));
+                EntityCrypto entityCrypto = new EntityCrypto(delegator,null); 
+                try {
+                    passwordToSend = entityCrypto.encrypt(keyValue, (Object) autoPassword);
+                } catch (GeneralException e) {
+                    Debug.logWarning(e, "Problem in encryption", module);
+                }
+                supposedUserLogin.set("currentPassword", HashCrypt.cryptUTF8(LoginServices.getHashType(), null, autoPassword));
                 supposedUserLogin.set("passwordHint", "Auto-Generated Password");
                 if ("true".equals(EntityUtilProperties.getPropertyValue("security", "password.email_password.require_password_change", delegator))){
                     supposedUserLogin.set("requirePasswordChange", "Y");
@@ -298,7 +333,7 @@ public class LoginEvents {
             if (emailTemplateSetting != null) {
                 String subject = emailTemplateSetting.getString("subject");
                 subject = FlexibleStringExpander.expandString(subject, UtilMisc.toMap("userLoginId", userLoginId));
-                serviceContext.put("subject", subject);                
+                serviceContext.put("subject", subject);
                 serviceContext.put("sendFrom", emailTemplateSetting.get("fromAddress"));
             } else {
                 serviceContext.put("subject", UtilProperties.getMessage(resource, "loginservices.password_reminder_subject", UtilMisc.toMap("userLoginId", userLoginId), UtilHttp.getLocale(request)));

Modified: ofbiz/trunk/applications/securityext/widget/EmailSecurityScreens.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/securityext/widget/EmailSecurityScreens.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/applications/securityext/widget/EmailSecurityScreens.xml (original)
+++ ofbiz/trunk/applications/securityext/widget/EmailSecurityScreens.xml Fri Nov 27 20:37:15 2015
@@ -24,7 +24,9 @@ under the License.
     <screen name="PasswordEmail">
         <section>
             <actions>
-                <property-map resource="SecurityExtUiLabels" map-name="uiLabelMap" global="true"/>
+                <property-map resource="EmailPassword" map-name="uiLabelMap" global="true"/>
+                <property-map resource="SecurityUiLabels" map-name="uiLabelMap" global="true"/>
+                <set field="baseEcommerceSecureUrl" value="${baseSecureUrl}"/>
             </actions>
             <widgets>
                 <platform-specific><html><html-template location="component://securityext/email/default/passwordemail.ftl"/></html></platform-specific>

Modified: ofbiz/trunk/framework/common/config/SecurityUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/config/SecurityUiLabels.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/config/SecurityUiLabels.xml (original)
+++ ofbiz/trunk/framework/common/config/SecurityUiLabels.xml Fri Nov 27 20:37:15 2015
@@ -83,6 +83,10 @@
         <value xml:lang="zh">把用户登录添加到安全组</value>
         <value xml:lang="zh-TW">把使用者登入增加到安全群組</value>
     </property>
+    <property key="AnswerSecurityQuestion">
+        <value xml:lang="en">Answer your Security Question</value>
+        <value xml:lang="en">Répondez à votre question de sécurité</value>
+    </property>
     <property key="CertComponent">
         <value xml:lang="de">Komponente</value>
         <value xml:lang="en">Component</value>
@@ -691,6 +695,14 @@
         <value xml:lang="zh">受保护的视图</value>
         <value xml:lang="zh-TW">受保護的檢視</value>
     </property>
+    <property key="ResetPassword">
+        <value xml:lang="en">Click Here To Reset Password</value>
+        <value xml:lang="fr">Cliquez ici pour créer un nouveau mot de passe</value>
+    </property>
+    <property key="SecurityAnswer">
+        <value xml:lang="en">Security Answer</value>
+        <value xml:lang="en">Réponse de sécurité</value>
+    </property>
     <property key="SecurityGroups">
         <value xml:lang="de">Sicherheitsgruppen</value>
         <value xml:lang="en">Security Groups</value>
@@ -725,6 +737,10 @@
         <value xml:lang="zh">安全组列表</value>
         <value xml:lang="zh-TW">安全群組清單</value>
     </property>
+    <property key="SecurityQuestion">
+        <value xml:lang="en">Security Question</value>
+        <value xml:lang="en">Question de sécurité</value>
+    </property>
     <property key="SecurityViewPermissionError">
         <value xml:lang="de">Sicherheitsfehler: Sie haben nicht die Berechtigung diese Seite anzusehen. ("SECURITY_VIEW" oder "SECURITY_ADMIN" benötigt) </value>
         <value xml:lang="en">SecurityViewPermissionError You do not have permission to view this page. ("SECURITY_VIEW" or "SECURITY_ADMIN" needed)</value>

Modified: ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml (original)
+++ ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml Fri Nov 27 20:37:15 2015
@@ -241,6 +241,10 @@
         <value xml:lang="zh">配置出错;请与客户服务联系。</value>
         <value xml:lang="zh-TW">設定有問題: 請聯絡客服.</value>
     </property>
+    <property key="loginevents.problem_getting_security_question_record">
+        <value xml:lang="en">Problem getting User Login Security Question record.</value>
+        <value xml:lang="fr">Problème durant la lecture de votre question de sécurité</value>
+    </property>
     <property key="loginevents.unable_to_login_tenant">
         <value xml:lang="en">You cannot login to this tenant</value>
         <value xml:lang="es">No puede conectarse con esta organización</value>
@@ -506,6 +510,10 @@
         <value xml:lang="zh">无法禁用旧的登录用户(写错误):${errorMessage}。</value>
         <value xml:lang="zh-TW">無法停用舊有使用者(寫入錯誤): ${errorMessage}.</value>
     </property>
+    <property key="loginservices.error_setting_security_question">
+        <value xml:lang="en">Exception thrown while setting security question for the UserLogin:</value>
+        <value xml:lang="fr">Problème durant l'écriture de votre question de sécurité</value>
+    </property>
     <property key="loginservices.ldap_authentication_failed">
         <value xml:lang="de">LDAP Anmeldung nicht möglich</value>
         <value xml:lang="en">LDAP authentication failed.</value>
@@ -789,6 +797,14 @@
         <value xml:lang="zh">密码不符合样式:${passwordPatternMessage} </value>
         <value xml:lang="zh-TW">密碼不符合格式:${passwordPatternMessage} </value>
     </property>
+    <property key="loginservices.security_answer_empty">
+        <value xml:lang="en">The security answer is missing</value>
+        <value xml:lang="fr">La question de sécurité manque</value>
+    </property>
+    <property key="loginservices.security_answer_not_match">
+        <value xml:lang="en">The answer does not match records, re-enter</value>
+        <value xml:lang="fr">Votre réponse à la question de sécurité ne correspond, essayez à nouveau.</value>
+    </property>
     <property key="loginservices.since_datetime">
         <value xml:lang="de">(seit ${disabledDateTime})</value>
         <value xml:lang="en">since ${disabledDateTime}.</value>

Modified: ofbiz/trunk/framework/common/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/servicedef/services.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/servicedef/services.xml (original)
+++ ofbiz/trunk/framework/common/servicedef/services.xml Fri Nov 27 20:37:15 2015
@@ -391,6 +391,8 @@ under the License.
         <attribute name="requirePasswordChange" type="String" mode="IN" optional="true"/>
         <attribute name="externalAuthId" type="String" mode="IN" optional="true"/>
         <attribute name="partyId" type="String" mode="IN" optional="true"/>
+        <attribute name="securityQuestion" type="String" mode="IN" optional="true"/>
+        <attribute name="securityAnswer" type="String" mode="IN" optional="true"/>
     </service>
     <service name="updateUserLoginId" engine="java" location="org.ofbiz.common.login.LoginServices" invoke="updateUserLoginId" auth="true">
         <description>Update a UserLoginId by creating a new one and expiring the old one</description>

Modified: ofbiz/trunk/framework/common/servicedef/services_security.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/servicedef/services_security.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/servicedef/services_security.xml (original)
+++ ofbiz/trunk/framework/common/servicedef/services_security.xml Fri Nov 27 20:37:15 2015
@@ -124,4 +124,20 @@ under the License.
         <attribute name="primaryPermission" type="String" mode="IN" optional="true" default-value="SECURITY"/>
     </service>
     
+    <service name="createUserLoginSecurityQuestion" engine="entity-auto" invoke="create" default-entity-name="UserLoginSecurityQuestion" auth="true">
+        <description>Create a UserLoginSecurityQuestion</description>
+        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="nonpk" mode="IN" optional="true"/>
+    </service>
+    <service name="updateUserLoginSecurityQuestion" engine="entity-auto" invoke="update" default-entity-name="UserLoginSecurityQuestion" auth="true">
+        <description>Update a UserLoginSecurityQuestion</description>
+        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="nonpk" mode="IN" optional="true"/>
+    </service>
+    <service name="removeUserLoginSecurityQuestion" engine="entity-auto" invoke="delete" default-entity-name="UserLoginSecurityQuestion" auth="true">
+        <description>Remove UserLoginSecurityQuestion</description>
+        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="nonpk" mode="IN" optional="true"/>
+    </service>
+    
 </services>

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=1716915&r1=1716914&r2=1716915&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 Fri Nov 27 20:37:15 2015
@@ -20,6 +20,7 @@
 package org.ofbiz.common.login;
 
 import java.sql.Timestamp;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -52,6 +53,7 @@ import org.ofbiz.entity.util.EntityQuery
 import org.ofbiz.entity.util.EntityUtilProperties;
 import org.ofbiz.security.Security;
 import org.ofbiz.service.DispatchContext;
+import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ModelService;
 import org.ofbiz.service.ServiceUtil;
@@ -473,6 +475,7 @@ public class LoginServices {
     public static Map<String, Object> createUserLogin(DispatchContext ctx, Map<String, ?> context) {
         Map<String, Object> result =  new LinkedHashMap<String, Object>();
         Delegator delegator = ctx.getDelegator();
+        LocalDispatcher dispatcher = ctx.getDispatcher();
         Security security = ctx.getSecurity();
         GenericValue loggedInUserLogin = (GenericValue) context.get("userLogin");
         List<String> errorMessageList = new LinkedList<String>();
@@ -490,6 +493,9 @@ public class LoginServices {
         String externalAuthId = (String) context.get("externalAuthId");
         String errMsg = null;
 
+        String questionEnumId = (String) context.get("securityQuestion");
+        String securityAnswer = (String) context.get("securityAnswer");
+        
         // security: don't create a user login if the specified partyId (if not empty) already exists
         // unless the logged in user has permission to do so (same partyId or PARTYMGR_CREATE)
         if (UtilValidate.isNotEmpty(partyId)) {
@@ -560,6 +566,21 @@ public class LoginServices {
             return ServiceUtil.returnError(errMsg);
         }
 
+        try {
+            if (UtilValidate.isNotEmpty(securityAnswer)) {
+                Map<String, Object> resultMap = new HashMap<String, Object>(); 
+                resultMap = dispatcher.runSync("createUserLoginSecurityQuestion",
+                        UtilMisc.toMap("userLogin", loggedInUserLogin, "userLoginId", userLoginId, "questionEnumId", questionEnumId, "securityAnswer", securityAnswer));
+                if (ServiceUtil.isError(resultMap)) {
+                    errMsg = ServiceUtil.getErrorMessage(resultMap);
+                    errorMessageList.add(errMsg);
+                    Debug.logError(errMsg, module);
+                }
+            }
+        } catch (GenericServiceException e1) {
+            errMsg = UtilProperties.getMessage(resource,"loginservices.error_setting_security_question", locale);
+            Debug.logError(e1, errMsg, module);
+        }
         result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
         return result;
     }

Modified: ofbiz/trunk/framework/common/webcommon/WEB-INF/common-controller.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/webcommon/WEB-INF/common-controller.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/webcommon/WEB-INF/common-controller.xml (original)
+++ ofbiz/trunk/framework/common/webcommon/WEB-INF/common-controller.xml Fri Nov 27 20:37:15 2015
@@ -72,6 +72,20 @@ under the License.
         <response name="success" type="view" value="forgotPassword"/>
         <response name="error" type="view" value="forgotPassword"/>
     </request-map>
+    <request-map uri="forgotPassword_step1">
+        <security https="true" auth="false"/>
+        <response name="success" type="view" value="forgotPassword_step1"/>
+    </request-map>
+    <request-map uri="forgotPassword_step2">
+        <security auth="false" https="true"></security>
+        <response name="success" type="view" value="forgotPassword_step2" />
+    </request-map>
+    <request-map uri="forgotPassword_step3">
+        <security https="true" auth="false"/>
+         <event type="java" path="org.ofbiz.securityext.login.LoginEvents" invoke="forgotPassword"/>
+        <response name="success" type="view" value="login"/>
+        <response name="error" type="view" value="forgotPassword_step2"/>
+     </request-map>
     <request-map uri="passwordChange">
         <security https="true" auth="false"/>
         <response name="success" type="view" value="requirePasswordChange"/>
@@ -289,4 +303,6 @@ under the License.
     <view-map name="LookupGeo" type="screen" page="component://common/widget/LookupScreens.xml#LookupGeo"/>
     <view-map name="LookupGeoName" type="screen" page="component://common/widget/LookupScreens.xml#LookupGeoName"/>
     <view-map name="LookupLocale" type="screen" page="component://common/widget/LookupScreens.xml#LookupLocale"/>
+    <view-map name="forgotPassword_step1" type="screen" page="component://common/widget/CommonScreens.xml#forgotPassword_step1"/>
+    <view-map name="forgotPassword_step2" type="screen" page="component://common/widget/CommonScreens.xml#forgotPassword_step2"/>
 </site-conf>

Modified: ofbiz/trunk/framework/common/webcommon/changePassword.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/webcommon/changePassword.ftl?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/webcommon/changePassword.ftl (original)
+++ ofbiz/trunk/framework/common/webcommon/changePassword.ftl Fri Nov 27 20:37:15 2015
@@ -22,6 +22,8 @@ under the License.
 
 <center>
 <div class="screenlet login-screenlet">
+<#assign forgotPwdFlag = parameters.forgotPwdFlag?has_content />
+<div class="login-screenlet">
   <div class="screenlet-title-bar">
     <h3>${uiLabelMap.CommonPasswordChange}</h3>
   </div>
@@ -29,16 +31,23 @@ under the License.
     <form method="post" action="<@o...@ofbizUrl>" name="loginform">
       <input type="hidden" name="requirePasswordChange" value="Y"/>
       <input type="hidden" name="USERNAME" value="${username}"/>
-      <input type="hidden" name="userTenantId" value="${tenantId!}"/>
+      <input type="hidden" name="userTenantId" value="${tenantId}"/>
+      <input type="hidden" name="forgotPwdFlag" value="${parameters.forgotPwdFlag!}" />
       <table cellspacing="0">
         <tr>
           <td class="label">${uiLabelMap.CommonUsername}</td>
           <td>${username}</td>
         </tr>
-        <tr>
-          <td class="label">${uiLabelMap.CommonCurrentPassword}</td>
-          <td><input type="password" name="PASSWORD" value="" size="20"/></td>
-        </tr>
+        <#if forgotPwdFlag?has_content && forgotPwdFlag?string == "true">
+          <tr>
+            <td><input type="hidden" name="PASSWORD" value="${parameters.password!}" size="20"/></td>
+          </tr>
+        <#else>
+          <tr>
+            <td class="label">${uiLabelMap.CommonCurrentPassword}</td>
+            <td><input type="password" name="PASSWORD" value="" size="20" /></td>
+          </tr>
+        </#if>
         <tr>
           <td class="label">${uiLabelMap.CommonNewPassword}</td>
           <td><input type="password" name="newPassword" value="" size="20"/></td>
@@ -47,6 +56,19 @@ under the License.
           <td class="label">${uiLabelMap.CommonNewPasswordVerify}</td>
           <td><input type="password" name="newPasswordVerify" value="" size="20"/></td>
         </tr>
+        <#if securityQuestion?has_content>
+          <tr>
+            <td class="label">${uiLabelMap.SecurityQuestiom}</td>
+            <td>
+              <input type="hidden" name="securityQuestion" value="${securityQuestion.enumId!}" />
+                ${securityQuestion.description!}
+            </td>
+          </tr>
+          <tr>
+            <td class="label">${uiLabelMap.SecurityAnswer}</td>
+            <td><input type="text" class='inputBox' name="securityAnswer" id="SECURITY_ANSWER" value="" maxlength="100" /></td>
+          </tr>
+        </#if>
         <tr>
           <td colspan="2" align="center">
             <input type="submit" value="${uiLabelMap.CommonSubmit}"/>

Modified: ofbiz/trunk/framework/common/webcommon/forgotPassword.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/webcommon/forgotPassword.ftl?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/webcommon/forgotPassword.ftl (original)
+++ ofbiz/trunk/framework/common/webcommon/forgotPassword.ftl Fri Nov 27 20:37:15 2015
@@ -23,7 +23,7 @@ under the License.
       <h3>${uiLabelMap.CommonForgotYourPassword}?</h3>
     </div>
     <div class="screenlet-body">
-      <form method="post" action="<@o...@ofbizUrl>" name="forgotpassword">
+      <form method="post" action="<@o...@ofbizUrl>" name="getSecurityQuestion">
         <table class="basic-table" cellspacing="0">
           <tr>
             <td class="label">${uiLabelMap.CommonUsername}</td>
@@ -31,11 +31,15 @@ under the License.
           </tr>
           <tr>
             <td colspan="2" align="center">
-              <input type="submit" name="GET_PASSWORD_HINT" class="smallSubmit" value="${uiLabelMap.CommonGetPasswordHint}"/>&nbsp;<input type="submit" name="EMAIL_PASSWORD" class="smallSubmit" value="${uiLabelMap.CommonEmailPassword}"/>
+              <input type="submit" class="smallSubmit" value="${uiLabelMap.CommonContinue}"/>
+            </td>
+          </tr>
+          <tr>
+            <td colspan="2" align="center">
+              <a href='<@o...@ofbizUrl>' class="buttontext">${uiLabelMap.CommonGoBack}</a>
             </td>
           </tr>
         </table>
-        <a href='<@o...@ofbizUrl>' class="button">${uiLabelMap.CommonGoBack}</a>
         <input type="hidden" name="JavaScriptEnabled" value="N"/>
       </form>
     </div>

Added: ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl?rev=1716915&view=auto
==============================================================================
--- ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl (added)
+++ ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl Fri Nov 27 20:37:15 2015
@@ -0,0 +1,77 @@
+<#--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<center>
+  <div class="screenlet login-screenlet">
+    <div class="screenlet-title-bar">
+      <#if securityQuestion?has_content>
+        <h3>${uiLabelMap.AnswerSecurityQuestion}</h3>
+      <#else>
+        <h3>${uiLabelMap.CommonForgotYourPassword}</h3>
+      </#if>
+    </div>
+    <div class="screenlet-body">
+      <form method="post" action="<@o...@ofbizUrl>" name="forgotpassword">
+        <table class="basic-table" cellspacing="0">
+          <#if userLoginId?has_content>
+            <#if securityQuestion?has_content>
+              <tr>
+                <td class="label">${uiLabelMap.SecurityQuestion}</td>
+                <td>
+                   ${securityQuestion.description!}
+                   <input type="hidden" name="securityQuestion" value="${securityQuestion.enumId!}" />
+                   <input type="hidden" name="USERNAME" value="${userLoginId!}" />
+                </td>
+              </tr>
+              <tr>
+                <td class="label">${uiLabelMap.SecurityAnswer}</td>
+                <td>
+                  <input type="text" name="securityAnswer" class="" value="" />&nbsp;
+                </td>
+              </tr>
+            <#else>
+              <tr>
+                <td class="label">${uiLabelMap.CommonUsername}</td>
+                <td><input type="text" size="20" name="USERNAME" value="<#if requestParameters.USERNAME?has_content>${requestParameters.USERNAME}<#elseif autoUserLogin?has_content>${autoUserLogin.userLoginId}</#if>" /></td>
+              </tr>
+            </#if>
+            <tr>
+              <td colspan="2" align="center">
+                <input type="submit" name="GET_PASSWORD_HINT" class="smallSubmit" value="${uiLabelMap.CommonGetPasswordHint}" />&nbsp;
+                <input type="submit" name="EMAIL_PASSWORD" class="smallSubmit" value="${uiLabelMap.CommonEmailPassword}" />
+              </td>
+            </tr>
+          <#else>
+            <tr>
+              <td colspan="2" align="center">
+                ${uiLabelMap.PartyUserLoginMissingError}
+              </td>
+            </tr>
+          </#if>
+          <tr>
+            <td colspan="2" align="center">
+              <a href='#' class="buttontext" onclick="window.history.back();">${uiLabelMap.CommonGoBack}</a>
+            </td>
+          </tr>
+        </table>
+        <input type="hidden" name="JavaScriptEnabled" value="N" />
+      </form>
+    </div>
+  </div>
+</center>
\ No newline at end of file

Propchange: ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/common/webcommon/getSecurityQuestion.ftl
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/trunk/framework/common/webcommon/login.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/webcommon/login.ftl?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/webcommon/login.ftl (original)
+++ ofbiz/trunk/framework/common/webcommon/login.ftl Fri Nov 27 20:37:15 2015
@@ -60,7 +60,7 @@ under the License.
         </table>
         <input type="hidden" name="JavaScriptEnabled" value="N"/>
         <br />
-        <a href="<@o...@ofbizUrl>">${uiLabelMap.CommonForgotYourPassword}?</a>
+        <a href="<@o...@ofbizUrl>">${uiLabelMap.CommonForgotYourPassword}?</a>
       </form>
     </div>
   </div>

Modified: ofbiz/trunk/framework/common/widget/CommonScreens.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/widget/CommonScreens.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/widget/CommonScreens.xml (original)
+++ ofbiz/trunk/framework/common/widget/CommonScreens.xml Fri Nov 27 20:37:15 2015
@@ -574,6 +574,16 @@ under the License.
 
     <screen name="requirePasswordChange">
         <section>
+            <actions>
+                <set field="userLoginId" from-field="parameters.USERNAME"/>
+                <entity-and entity-name="UserLoginSecurityQuestion" list="securityQuestions">
+                    <field-map field-name="userLoginId" />
+                </entity-and>
+                <set field="questionEnumId" from-field="securityQuestions[0].questionEnumId" />
+                <entity-one entity-name="Enumeration" value-field="securityQuestion">
+                    <field-map field-name="enumId" from-field="questionEnumId" />
+                </entity-one>
+            </actions>
             <widgets>
                 <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
                     <decorator-section name="body">
@@ -586,6 +596,44 @@ under the License.
         </section>
     </screen>
 
+    <screen name="forgotPassword_step1">
+        <section>
+            <widgets>
+                <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
+                    <decorator-section name="body">
+                        <platform-specific>
+                            <html><html-template location="component://common/webcommon/forgotPassword.ftl"/></html>
+                        </platform-specific>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+
+    <screen name="forgotPassword_step2">
+        <section>
+            <actions>
+                <set field="userLoginId" from-field="parameters.USERNAME"/>
+                <entity-and entity-name="UserLoginSecurityQuestion" list="securityQuestions">
+                    <field-map field-name="userLoginId" />
+                </entity-and>
+                <set field="questionEnumId" from-field="securityQuestions[0].questionEnumId" />
+                <entity-one entity-name="Enumeration" value-field="securityQuestion">
+                    <field-map field-name="enumId" from-field="questionEnumId"/>
+                </entity-one> 
+            </actions>
+            <widgets>
+                <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}">
+                    <decorator-section name="body">
+                        <platform-specific>
+                           <html><html-template location="component://common/webcommon/getSecurityQuestion.ftl"/></html>
+                        </platform-specific>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+    
     <screen name="forgotPassword">
         <section>
             <widgets>

Modified: ofbiz/trunk/framework/common/widget/SecurityForms.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/widget/SecurityForms.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/widget/SecurityForms.xml (original)
+++ ofbiz/trunk/framework/common/widget/SecurityForms.xml Fri Nov 27 20:37:15 2015
@@ -75,6 +75,14 @@ under the License.
                 <option key="N" description="${uiLabelMap.CommonN}"/>
             </drop-down>
         </field>
+        <field name="securityQuestion">
+          <drop-down allow-empty="true">
+              <entity-options entity-name="Enumeration" key-field-name="enumId" description="${description}">
+                 <entity-constraint name="enumTypeId" operator="equals" value="SQ_STANDARD" /> 
+              </entity-options>
+          </drop-down>
+        </field>
+        <field name="securityAnswer" title="${uiLabelMap.SecurityAnswer}"><text /></field>
         <field name="submitButton" title="${uiLabelMap.CommonSave}" widget-style="smallSubmit"><submit button-type="text-link"/></field>
         <field name="cancelLink" title=" " widget-style="smallSubmit">
             <hyperlink target="${cancelPage}" also-hidden="false" description="${uiLabelMap.CommonCancelDone}">

Modified: ofbiz/trunk/framework/security/config/security.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/config/security.properties?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/security/config/security.properties (original)
+++ ofbiz/trunk/framework/security/config/security.properties Fri Nov 27 20:37:15 2015
@@ -124,3 +124,5 @@ default.error.response.view=view:viewBlo
 
 # If false, then no externalLoginKey parameters will be added to cross-webapp urls
 security.login.externalLoginKey.enabled=true
+#Security key used to encrypt and decrypt the autogenerated password in forgot password functionality.
+login.secret_key_string=Secret Key
\ No newline at end of file

Added: ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml?rev=1716915&view=auto
==============================================================================
--- ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml (added)
+++ ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml Fri Nov 27 20:37:15 2015
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<entity-engine-xml>
+    <!-- OFBiz Core security -->
+
+    <EnumerationType enumTypeId="SECURITY_QUESTION" description="Security Question"/>
+    <EnumerationType enumTypeId="SQ_CUSTOM" parentTypeId="SECURITY_QUESTION" description="Custom Security Question"/>
+    <EnumerationType enumTypeId="SQ_STANDARD" parentTypeId="SECURITY_QUESTION" description="Standard Security Question"/>
+    <Enumeration enumId="SQ_STD_NCKNM" enumTypeId="SQ_STANDARD" enumCode="" sequenceId="0" description="What is your nick name"/>
+    <Enumeration enumId="SQ_STD_MOTNM" enumTypeId="SQ_STANDARD" enumCode="" sequenceId="1" description="What is your mother's maiden name"/>
+    <Enumeration enumId="SQ_STD_FAVTCH" enumTypeId="SQ_STANDARD" enumCode="" sequenceId="2" description="What is your favorite teacher's name"/>
+    <Enumeration enumId="SQ_STD_PETNM" enumTypeId="SQ_STANDARD" enumCode="" sequenceId="2" description="What is your pet's name"/>
+    <Enumeration enumId="SQ_STD_BSTFRND" enumTypeId="SQ_STANDARD" enumCode="" sequenceId="3" description="Who is your best childhood friend"/>
+</entity-engine-xml>

Propchange: ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/security/data/SecurityTypeDemoData.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: ofbiz/trunk/framework/security/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/entitydef/entitymodel.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/security/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/framework/security/entitydef/entitymodel.xml Fri Nov 27 20:37:15 2015
@@ -231,4 +231,17 @@ under the License.
       <prim-key field="viewNameId"/>
       <prim-key field="userLoginId"/>
     </entity>
+    <entity entity-name="UserLoginSecurityQuestion" package-name="org.ofbiz.security.login">
+      <field name="questionEnumId" type="id-ne" />
+      <field name="userLoginId" type="id-vlong-ne" />
+      <field name="securityAnswer" type="description" />
+      <prim-key field="questionEnumId"/>
+      <prim-key field="userLoginId"/>
+      <relation rel-entity-name="Enumeration" type="one" fk-name="SECQ_ENUM">
+        <key-map field-name="questionEnumId" rel-field-name="enumId"/>
+      </relation>
+      <relation rel-entity-name="UserLogin" type="one" fk-name="ULGNSECQ_ULGN">
+        <key-map field-name="userLoginId"/>
+      </relation>
+    </entity>
 </entitymodel>

Modified: ofbiz/trunk/framework/security/ofbiz-component.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/ofbiz-component.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/framework/security/ofbiz-component.xml (original)
+++ ofbiz/trunk/framework/security/ofbiz-component.xml Fri Nov 27 20:37:15 2015
@@ -30,4 +30,5 @@ under the License.
     <!-- NOTE: comment this line out to ensure no resetting of passwords -->
     <entity-resource type="data" reader-name="demo" loader="main" location="data/PasswordSecurityData.xml"/>
     <entity-resource type="data" reader-name="demo" loader="main" location="data/SecurityGroupDemoData.xml"/>
+    <entity-resource type="data" reader-name="demo" loader="main" location="data/SecurityTypeDemoData.xml"/>
 </ofbiz-component>

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=1716915&r1=1716914&r2=1716915&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 Fri Nov 27 20:37:15 2015
@@ -56,15 +56,18 @@ import org.ofbiz.base.util.UtilPropertie
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
+import org.ofbiz.entity.EntityCryptoException;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.condition.EntityCondition;
 import org.ofbiz.entity.condition.EntityConditionList;
 import org.ofbiz.entity.condition.EntityOperator;
 import org.ofbiz.entity.model.ModelEntity;
+import org.ofbiz.entity.model.ModelField;
 import org.ofbiz.entity.serialize.XmlSerializer;
 import org.ofbiz.entity.transaction.GenericTransactionException;
 import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.entity.util.EntityCrypto;
 import org.ofbiz.entity.util.EntityQuery;
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.entity.util.EntityUtilProperties;
@@ -87,7 +90,9 @@ public class LoginWorker {
 
     public static final String EXTERNAL_LOGIN_KEY_ATTR = "externalLoginKey";
     public static final String X509_CERT_ATTR = "SSLx509Cert";
+    public static final String securityProperties = "security.properties";
 
+    private static final String keyValue = UtilProperties.getPropertyValue(securityProperties, "login.secret_key_string");
     /** This Map is keyed by the randomly generated externalLoginKey and the value is a UserLogin GenericValue object */
     public static Map<String, GenericValue> externalLoginKeys = new ConcurrentHashMap<String, GenericValue>();
 
@@ -125,7 +130,7 @@ public class LoginWorker {
      * Gets (and creates if necessary) a key to be used for an external login parameter
      */
     public static String getExternalLoginKey(HttpServletRequest request) {
-    	Delegator delegator = (Delegator) request.getAttribute("delegator");
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
         boolean externalLoginKeyEnabled = "true".equals(EntityUtilProperties.getPropertyValue("security", "security.login.externalLoginKey.enabled", "true", delegator));
         if (!externalLoginKeyEnabled) {
             return null;
@@ -364,9 +369,27 @@ public class LoginWorker {
      */
     public static String login(HttpServletRequest request, HttpServletResponse response) {
         HttpSession session = request.getSession();
-
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
         String username = request.getParameter("USERNAME");
         String password = request.getParameter("PASSWORD");
+        String forgotPwdFlag = request.getParameter("forgotPwdFlag");
+        
+        // password decryption
+        EntityCrypto entityDeCrypto = null;
+        try {
+            entityDeCrypto = new EntityCrypto(delegator, null);
+        } catch (EntityCryptoException e1) {
+            Debug.logError(e1.getMessage(), module);
+        }
+        
+        if(entityDeCrypto != null && "true".equals(forgotPwdFlag)) {
+            try {
+                Object decryptedPwd = entityDeCrypto.decrypt(keyValue, ModelField.EncryptMethod.TRUE, password);
+                password = decryptedPwd.toString();
+            } catch (GeneralException e) {
+                Debug.logError(e, "Current Password Decryption failed", module);
+            }
+        }
 
         if (username == null) username = (String) session.getAttribute("USERNAME");
         if (password == null) password = (String) session.getAttribute("PASSWORD");
@@ -395,7 +418,6 @@ public class LoginWorker {
         boolean setupNewDelegatorEtc = false;
 
         LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
-        Delegator delegator = (Delegator) request.getAttribute("delegator");
         ServletContext servletContext = session.getServletContext();
 
         // if a tenantId was passed in, see if the userLoginId is associated with that tenantId (can use any delegator for this, entity is not tenant-specific)
@@ -869,7 +891,7 @@ public class LoginWorker {
 
     // preprocessor method to login a user from a HTTP request header (configured in security.properties)
     public static String checkRequestHeaderLogin(HttpServletRequest request, HttpServletResponse response) {
-    	Delegator delegator = (Delegator) request.getAttribute("delegator");
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
         String httpHeader = EntityUtilProperties.getPropertyValue("security", "security.login.http.header", null, delegator);
 
         // make sure the header field is set in security.properties; if not, then this is disabled and just return
@@ -894,7 +916,7 @@ public class LoginWorker {
 
     // preprocessor method to login a user from HttpServletRequest.getRemoteUser() (configured in security.properties)
     public static String checkServletRequestRemoteUserLogin(HttpServletRequest request, HttpServletResponse response) {
-    	Delegator delegator = (Delegator) request.getAttribute("delegator");
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
         Boolean allowRemoteUserLogin = "true".equals(EntityUtilProperties.getPropertyValue("security", "security.login.http.servlet.remoteuserlogin.allow", "false", delegator));
         // make sure logging users via remote user is allowed in security.properties; if not just return
         if (allowRemoteUserLogin) {
@@ -917,7 +939,7 @@ public class LoginWorker {
     }
     // preprocessor method to login a user w/ client certificate see security.properties to configure the pattern of CN
     public static String check509CertLogin(HttpServletRequest request, HttpServletResponse response) {
-    	Delegator delegator = (Delegator) request.getAttribute("delegator");
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
         boolean doCheck = "true".equalsIgnoreCase(EntityUtilProperties.getPropertyValue("security", "security.login.cert.allow", "true", delegator));
         if (doCheck) {
             HttpSession session = request.getSession();

Modified: ofbiz/trunk/specialpurpose/ecommerce/script/org/ofbiz/ecommerce/customer/CustomerEvents.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/script/org/ofbiz/ecommerce/customer/CustomerEvents.xml?rev=1716915&r1=1716914&r2=1716915&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/ecommerce/script/org/ofbiz/ecommerce/customer/CustomerEvents.xml (original)
+++ ofbiz/trunk/specialpurpose/ecommerce/script/org/ofbiz/ecommerce/customer/CustomerEvents.xml Fri Nov 27 20:37:15 2015
@@ -415,6 +415,14 @@ under the License.
         <set field="createProductStoreRoleMap.productStoreId" from-field="parameters.emailProductStoreId"/>
         <call-service service-name="createProductStoreRole" in-map-name="createProductStoreRoleMap"/>
 
+        <!--Create User Login Security Question if entered by the user-->
+        <if-not-empty field="parameters.SECURITY_ANSWER">
+            <set field="createULSQCtx.userLoginId" from-field="parameters.USERNAME"/>
+            <set field="createULSQCtx.questionEnumId" from-field="parameters.securityQuestion"/>
+            <set field="createULSQCtx.answer" from-field="parameters.SECURITY_ANSWER"/>
+            <call-service service-name="createUserLoginSecurityQuestion" in-map-name="createULSQCtx" />
+        </if-not-empty>
+
         <!-- send off the registration email -->
         <if-not-empty field="emailContext.emailAddress">
             <set from-field="parameters.emailProductStoreId" field="storeEmailLookup.productStoreId"/>