From 951765ccd0ee3fd090826e896eacfe7b7e5f5070 Mon Sep 17 00:00:00 2001 From: Elaine Tan Date: Thu, 13 Sep 2012 16:29:23 +0800 Subject: [PATCH] IDEMPIERE-375 Implement Forgot my Password - add validation to check new password differ from old password and change the security question design --- .../oracle/910_IDEMPIERE-375.sql | 36 +++++ .../postgresql/910_IDEMPIERE-375.sql | 36 +++++ .../src/org/compiere/model/MSysConfig.java | 1 + .../src/org/compiere/apps/ALogin.java | 49 ++++--- .../webui/panel/ChangePasswordPanel.java | 37 +++-- .../webui/panel/ResetPasswordPanel.java | 136 ++++++++++++++---- 6 files changed, 221 insertions(+), 74 deletions(-) create mode 100644 migration/360lts-release/oracle/910_IDEMPIERE-375.sql create mode 100644 migration/360lts-release/postgresql/910_IDEMPIERE-375.sql diff --git a/migration/360lts-release/oracle/910_IDEMPIERE-375.sql b/migration/360lts-release/oracle/910_IDEMPIERE-375.sql new file mode 100644 index 0000000000..2468a24ef1 --- /dev/null +++ b/migration/360lts-release/oracle/910_IDEMPIERE-375.sql @@ -0,0 +1,36 @@ +-- Sep 12, 2012 6:56:41 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO AD_SysConfig (AD_SysConfig_ID,EntityType,ConfigurationLevel,Value,Description,AD_SysConfig_UU,Created,Updated,AD_Client_ID,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name) VALUES (200020,'D','S','Y','New password must differs from the old password','13b5a576-7b91-471b-8b40-05589dd585f7',TO_DATE('2012-09-12 18:56:39','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2012-09-12 18:56:39','YYYY-MM-DD HH24:MI:SS'),0,0,100,'Y',100,'CHANGE_PASSWORD_MUST_DIFFER') +; + +-- Sep 12, 2012 6:57:05 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +UPDATE AD_Column SET FieldLength=1024,Updated=TO_DATE('2012-09-12 18:57:05','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=200457 +; + +-- Sep 12, 2012 6:57:13 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +ALTER TABLE AD_User MODIFY SecurityQuestion NVARCHAR2(1024) DEFAULT NULL +; + +-- Sep 12, 2012 6:58:41 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,EntityType,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,AD_Client_ID,AD_Org_ID,Created) VALUES ('E','New Password must differ from Old Password',200066,'U','0d873a03-0980-4725-8a4f-a6954e4ee59e','NewPasswordMustDiffer','Y',TO_DATE('2012-09-12 18:58:40','YYYY-MM-DD HH24:MI:SS'),100,100,0,0,TO_DATE('2012-09-12 18:58:40','YYYY-MM-DD HH24:MI:SS')) +; + +-- Sep 12, 2012 6:58:41 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO AD_Message_Trl (AD_Language,AD_Message_ID, MsgText,MsgTip, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Message_Trl_UU ) SELECT l.AD_Language,t.AD_Message_ID, t.MsgText,t.MsgTip, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Message t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Message_ID=200066 AND NOT EXISTS (SELECT * FROM AD_Message_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Message_ID=t.AD_Message_ID) +; + +-- Sep 12, 2012 6:58:45 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +UPDATE AD_Message SET EntityType='D',Updated=TO_DATE('2012-09-12 18:58:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200066 +; + +UPDATE AD_User u SET SecurityQuestion = ( +SELECT MAX(m.MsgText) FROM AD_Message m WHERE m.Value = u.SecurityQuestion) +WHERE u.SecurityQuestion IS NOT NULL; + +SELECT register_migration_script('910_IDEMPIERE-375.sql') FROM dual +; \ No newline at end of file diff --git a/migration/360lts-release/postgresql/910_IDEMPIERE-375.sql b/migration/360lts-release/postgresql/910_IDEMPIERE-375.sql new file mode 100644 index 0000000000..9a48a4c4e3 --- /dev/null +++ b/migration/360lts-release/postgresql/910_IDEMPIERE-375.sql @@ -0,0 +1,36 @@ +-- Sep 12, 2012 6:56:41 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO AD_SysConfig (AD_SysConfig_ID,EntityType,ConfigurationLevel,Value,Description,AD_SysConfig_UU,Created,Updated,AD_Client_ID,AD_Org_ID,CreatedBy,IsActive,UpdatedBy,Name) VALUES (200020,'D','S','Y','New password must differs from the old password','13b5a576-7b91-471b-8b40-05589dd585f7',TO_TIMESTAMP('2012-09-12 18:56:39','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2012-09-12 18:56:39','YYYY-MM-DD HH24:MI:SS'),0,0,100,'Y',100,'CHANGE_PASSWORD_MUST_DIFFER') +; + +-- Sep 12, 2012 6:57:05 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +UPDATE AD_Column SET FieldLength=1024,Updated=TO_TIMESTAMP('2012-09-12 18:57:05','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=200457 +; + +-- Sep 12, 2012 6:57:13 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO t_alter_column values('ad_user','SecurityQuestion','VARCHAR(1024)',null,'NULL') +; + +-- Sep 12, 2012 6:58:41 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,EntityType,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,AD_Client_ID,AD_Org_ID,Created) VALUES ('E','New Password must differ from Old Password',200066,'U','0d873a03-0980-4725-8a4f-a6954e4ee59e','NewPasswordMustDiffer','Y',TO_TIMESTAMP('2012-09-12 18:58:40','YYYY-MM-DD HH24:MI:SS'),100,100,0,0,TO_TIMESTAMP('2012-09-12 18:58:40','YYYY-MM-DD HH24:MI:SS')) +; + +-- Sep 12, 2012 6:58:41 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +INSERT INTO AD_Message_Trl (AD_Language,AD_Message_ID, MsgText,MsgTip, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Message_Trl_UU ) SELECT l.AD_Language,t.AD_Message_ID, t.MsgText,t.MsgTip, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Message t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Message_ID=200066 AND NOT EXISTS (SELECT * FROM AD_Message_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Message_ID=t.AD_Message_ID) +; + +-- Sep 12, 2012 6:58:45 PM SGT +-- IDEMPIERE-375 Implement Forgot my Password +UPDATE AD_Message SET EntityType='D',Updated=TO_TIMESTAMP('2012-09-12 18:58:45','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200066 +; + +UPDATE AD_User u SET SecurityQuestion = ( +SELECT MAX(m.MsgText) FROM AD_Message m WHERE m.Value = u.SecurityQuestion) +WHERE u.SecurityQuestion IS NOT NULL; + +SELECT register_migration_script('910_IDEMPIERE-375.sql') FROM dual +; \ No newline at end of file diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index 3fcab94481..12cb81d600 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -95,6 +95,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String USER_LOCKING_MAX_LOGIN_ATTEMPT = "USER_LOCKING_MAX_LOGIN_ATTEMPT"; public static final String USER_LOCKING_MAX_INACTIVE_PERIOD_DAY = "USER_LOCKING_MAX_INACTIVE_PERIOD_DAY"; public static final String USER_LOCKING_MAX_PASSWORD_AGE_DAY = "USER_LOCKING_MAX_PASSWORD_AGE_DAY"; + public static final String CHANGE_PASSWORD_MUST_DIFFER = "CHANGE_PASSWORD_MUST_DIFFER"; public static final String ProductUOMConversionUOMValidate = "ProductUOMConversionUOMValidate"; public static final String ProductUOMConversionRateValidate = "ProductUOMConversionRateValidate"; public static final String SYSTEM_INSERT_CHANGELOG = "SYSTEM_INSERT_CHANGELOG"; diff --git a/org.adempiere.ui.swing/src/org/compiere/apps/ALogin.java b/org.adempiere.ui.swing/src/org/compiere/apps/ALogin.java index 25aaad2561..3d05870ddd 100644 --- a/org.adempiere.ui.swing/src/org/compiere/apps/ALogin.java +++ b/org.adempiere.ui.swing/src/org/compiere/apps/ALogin.java @@ -120,9 +120,6 @@ public final class ALogin extends CDialog private static final int CONNECTED_OK = 0; private static final int CONNECTED_OK_WITH_PASSWORD_EXPIRED = 1; -/* private static final int NO_OF_SECURITY_QUESTION = 5; - private static final String SECURITY_QUESTION_PREFIX = "SecurityQuestion_"; -*/ private CPanel mainPanel = new CPanel(new BorderLayout()); private CTabbedPane loginTabPane = new CTabbedPane(); private CPanel connectionPanel = new CPanel(); @@ -169,11 +166,11 @@ public final class ALogin extends CDialog private JPasswordField txtNewPassword = new JPasswordField(); private JPasswordField txtRetypeNewPassword = new JPasswordField(); // -/* private CLabel lblSecurityQuestion = new CLabel(); + private CLabel lblSecurityQuestion = new CLabel(); private CLabel lblAnswer = new CLabel(); - private VComboBox lstSecurityQuestion = new VComboBox(); + private CTextField txtSecurityQuestion = new CTextField(); private CTextField txtAnswer = new CTextField(); -*/ + /** Server Connection */ private CConnection m_cc; /** Application User */ @@ -382,22 +379,18 @@ public final class ALogin extends CDialog lblRetypeNewPassword.setHorizontalAlignment(SwingConstants.RIGHT); lblRetypeNewPassword.setText(Msg.getMsg(m_ctx, "New Password Confirm")); -/* lstSecurityQuestion.setName("lstSecurityQuestion"); + txtSecurityQuestion.setName("txtSecurityQuestion"); lblSecurityQuestion.setRequestFocusEnabled(false); - lblSecurityQuestion.setLabelFor(lstSecurityQuestion); + lblSecurityQuestion.setLabelFor(txtSecurityQuestion); lblSecurityQuestion.setHorizontalAlignment(SwingConstants.RIGHT); lblSecurityQuestion.setText(Msg.getMsg(m_ctx, "SecurityQuestion")); - lstSecurityQuestion.removeAllItems(); - for (int i = 1; i <= NO_OF_SECURITY_QUESTION; i++) - lstSecurityQuestion.addItem(new ValueNamePair(SECURITY_QUESTION_PREFIX + i, Msg.getMsg(m_ctx, SECURITY_QUESTION_PREFIX + i))); - txtAnswer.setName("txtAnswer"); lblAnswer.setRequestFocusEnabled(false); lblAnswer.setLabelFor(txtAnswer); lblAnswer.setHorizontalAlignment(SwingConstants.RIGHT); lblAnswer.setText(Msg.getMsg(m_ctx, "Answer")); -*/ + changePasswordPanel.setLayout(changePasswordPanelLayout); changePasswordPanel.add(lblOldPassword, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 @@ -412,15 +405,15 @@ public final class ALogin extends CDialog ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(12, 12, 5, 5), 0, 0)); changePasswordPanel.add(txtRetypeNewPassword, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(12, 0, 5, 12), 0, 0)); -/* changePasswordPanel.add(lblSecurityQuestion, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0 + changePasswordPanel.add(lblSecurityQuestion, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0 ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(12, 12, 5, 5), 0, 0)); - changePasswordPanel.add(lstSecurityQuestion, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0 + changePasswordPanel.add(txtSecurityQuestion, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(12, 0, 5, 12), 0, 0)); changePasswordPanel.add(lblAnswer, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0 ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(12, 12, 5, 5), 0, 0)); changePasswordPanel.add(txtAnswer, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(12, 0, 5, 12), 0, 0)); -*/ loginTabPane.add(changePasswordPanel, res.getString("ChangePassword")); + loginTabPane.add(changePasswordPanel, res.getString("ChangePassword")); loginTabPane.setEnabledAt(TAB_CHANGE_PASSWORD, false); // @@ -656,12 +649,9 @@ public final class ALogin extends CDialog String newPassword = new String(txtNewPassword.getPassword()); String retypeNewPassword = new String(txtRetypeNewPassword.getPassword()); -/* String securityQuestion = null; - if (lstSecurityQuestion.getSelectedItem() != null) - securityQuestion = ((ValueNamePair) lstSecurityQuestion.getSelectedItem()).getValue(); - + String securityQuestion = txtSecurityQuestion.getText(); String answer = txtAnswer.getText(); -*/ + if (Util.isEmpty(oldPassword)) { statusBar.setStatusLine(Msg.getMsg(m_ctx, "OldPasswordMandatory"), true); @@ -680,7 +670,7 @@ public final class ALogin extends CDialog return; } -/* if (Util.isEmpty(securityQuestion)) + if (Util.isEmpty(securityQuestion)) { statusBar.setStatusLine(Msg.getMsg(m_ctx, "SecurityQuestionMandatory"), true); return; @@ -691,13 +681,22 @@ public final class ALogin extends CDialog statusBar.setStatusLine(Msg.getMsg(m_ctx, "AnswerMandatory"), true); return; } -*/ + String m_userPassword = new String(m_pwd); if (!oldPassword.equals(m_userPassword)) { statusBar.setStatusLine(Msg.getMsg(m_ctx, "OldPasswordNoMatch"), true); return; } + + if (MSysConfig.getBooleanValue(MSysConfig.CHANGE_PASSWORD_MUST_DIFFER, true)) + { + if (oldPassword.equals(newPassword)) + { + statusBar.setStatusLine(Msg.getMsg(m_ctx, "NewPasswordMustDiffer"), true); + return; + } + } Trx trx = null; try @@ -721,9 +720,9 @@ public final class ALogin extends CDialog user.setPassword(newPassword); user.setIsExpired(false); -/* user.setSecurityQuestion(securityQuestion); + user.setSecurityQuestion(securityQuestion); user.setAnswer(answer); -*/ if (!user.save(trx.getTrxName())) + if (!user.save(trx.getTrxName())) { trx.rollback(); statusBar.setStatusLine("Could not update user", true); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ChangePasswordPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ChangePasswordPanel.java index 734e325eef..49a3609304 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ChangePasswordPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ChangePasswordPanel.java @@ -20,7 +20,6 @@ import java.util.Properties; import org.adempiere.exceptions.AdempiereException; import org.adempiere.webui.AdempiereIdGenerator; import org.adempiere.webui.LayoutUtils; -import org.adempiere.webui.component.Combobox; import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Textbox; @@ -29,6 +28,7 @@ import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.window.LoginWindow; +import org.compiere.model.MSysConfig; import org.compiere.model.MUser; import org.compiere.util.CLogger; import org.compiere.util.Env; @@ -75,10 +75,10 @@ public class ChangePasswordPanel extends Window implements EventListener private Label lblRetypeNewPassword; private Label lblSecurityQuestion; private Label lblAnswer; - private Combobox lstSecurityQuestion; private Textbox txtOldPassword; private Textbox txtNewPassword; private Textbox txtRetypeNewPassword; + private Textbox txtSecurityQuestion; private Textbox txtAnswer; public ChangePasswordPanel(Properties ctx, LoginWindow loginWindow, String userName, String userPassword, boolean show, KeyNamePair[] clientsKNPairs) @@ -168,7 +168,7 @@ public class ChangePasswordPanel extends Window implements EventListener td = new Td(); td.setSclass(ITheme.LOGIN_FIELD_CLASS); tr.appendChild(td); - td.appendChild(lstSecurityQuestion); + td.appendChild(txtSecurityQuestion); tr = new Tr(); tr.setId("rowAnswer"); @@ -215,18 +215,7 @@ public class ChangePasswordPanel extends Window implements EventListener lblAnswer = new Label(); lblAnswer.setId("lblAnswer"); lblAnswer.setValue(Msg.getMsg(m_ctx, "Answer")); - - lstSecurityQuestion = new Combobox(); - lstSecurityQuestion.setAutocomplete(true); - lstSecurityQuestion.setAutodrop(true); - lstSecurityQuestion.setId("lstSecurityQuestion"); - lstSecurityQuestion.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + lstSecurityQuestion.getId()); - lstSecurityQuestion.setWidth("220px"); - lstSecurityQuestion.getItems().clear(); - for (int i = 1; i <= ResetPasswordPanel.NO_OF_SECURITY_QUESTION; i++) - lstSecurityQuestion.appendItem(Msg.getMsg(m_ctx, ResetPasswordPanel.SECURITY_QUESTION_PREFIX + i), ResetPasswordPanel.SECURITY_QUESTION_PREFIX + i); - txtOldPassword = new Textbox(); txtOldPassword.setId("txtOldPassword"); txtOldPassword.setType("password"); @@ -248,6 +237,12 @@ public class ChangePasswordPanel extends Window implements EventListener txtRetypeNewPassword.setCols(25); txtRetypeNewPassword.setWidth("220px"); + txtSecurityQuestion = new Textbox(); + txtSecurityQuestion.setId("txtSecurityQuestion"); + txtSecurityQuestion.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + txtSecurityQuestion.getId()); + txtSecurityQuestion.setCols(25); + txtSecurityQuestion.setWidth("220px"); + txtAnswer = new Textbox(); txtAnswer.setId("txtAnswer"); // txtAnswer.setType("password"); @@ -273,12 +268,8 @@ public class ChangePasswordPanel extends Window implements EventListener { String oldPassword = txtOldPassword.getValue(); String newPassword = txtNewPassword.getValue(); - String retypeNewPassword = txtRetypeNewPassword.getValue(); - - String securityQuestion = null; - if (lstSecurityQuestion.getSelectedItem() != null) - securityQuestion = (String) lstSecurityQuestion.getSelectedItem().getValue(); - + String retypeNewPassword = txtRetypeNewPassword.getValue(); + String securityQuestion = txtSecurityQuestion.getValue(); String answer = txtAnswer.getValue(); if (Util.isEmpty(oldPassword)) @@ -298,6 +289,12 @@ public class ChangePasswordPanel extends Window implements EventListener if (!oldPassword.equals(m_userPassword)) throw new IllegalArgumentException(Msg.getMsg(m_ctx, "OldPasswordNoMatch")); + + if (MSysConfig.getBooleanValue(MSysConfig.CHANGE_PASSWORD_MUST_DIFFER, true)) + { + if (oldPassword.equals(newPassword)) + throw new IllegalArgumentException(Msg.getMsg(m_ctx, "NewPasswordMustDiffer")); + } Trx trx = null; try diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ResetPasswordPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ResetPasswordPanel.java index dede9b63f2..868776173f 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ResetPasswordPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ResetPasswordPanel.java @@ -23,7 +23,6 @@ import java.util.Properties; import org.adempiere.exceptions.AdempiereException; import org.adempiere.webui.AdempiereIdGenerator; import org.adempiere.webui.LayoutUtils; -import org.adempiere.webui.component.Combobox; import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Textbox; @@ -67,9 +66,7 @@ public class ResetPasswordPanel extends Window implements EventListener private static CLogger logger = CLogger.getCLogger(ResetPasswordPanel.class); - private static final int MAX_RESET_PASSWORD_TRIES = 3; - protected static final int NO_OF_SECURITY_QUESTION = 5; - protected static final String SECURITY_QUESTION_PREFIX = "SecurityQuestion_"; + private static final int MAX_RESET_PASSWORD_TRIES = 3; private static final String RESET_PASSWORD_MAIL_TEXT_NAME = "Reset Password"; private LoginWindow wndLogin; @@ -86,9 +83,11 @@ public class ResetPasswordPanel extends Window implements EventListener private Label lblSecurityQuestion; private Label lblAnswer; private Label lblUserId; - private Combobox lstSecurityQuestion; + private Label lblEmail; + private Textbox txtSecurityQuestion; private Textbox txtAnswer; private Textbox txtUserId; + private Textbox txtEmail; public ResetPasswordPanel(Properties ctx, LoginWindow loginWindow, String userName, boolean noSecurityQuestion) { @@ -100,6 +99,8 @@ public class ResetPasswordPanel extends Window implements EventListener initComponents(); init(); this.setId("resetPasswordPanel"); + + loadData(); } private void init() @@ -145,6 +146,18 @@ public class ResetPasswordPanel extends Window implements EventListener } else { + tr = new Tr(); + tr.setId("rowEmail"); + table.appendChild(tr); + td = new Td(); + tr.appendChild(td); + td.setSclass(ITheme.LOGIN_LABEL_CLASS); + td.appendChild(lblEmail); + td = new Td(); + td.setSclass(ITheme.LOGIN_FIELD_CLASS); + tr.appendChild(td); + td.appendChild(txtEmail); + tr = new Tr(); tr.setId("rowSecurityQuestion"); table.appendChild(tr); @@ -155,7 +168,7 @@ public class ResetPasswordPanel extends Window implements EventListener td = new Td(); td.setSclass(ITheme.LOGIN_FIELD_CLASS); tr.appendChild(td); - td.appendChild(lstSecurityQuestion); + td.appendChild(txtSecurityQuestion); tr = new Tr(); tr.setId("rowAnswer"); @@ -200,6 +213,10 @@ public class ResetPasswordPanel extends Window implements EventListener } else { + lblEmail = new Label(); + lblEmail.setId("lblEmail"); + lblEmail.setValue(Msg.getMsg(m_ctx, "EMail")); + lblSecurityQuestion = new Label(); lblSecurityQuestion.setId("lblSecurityQuestion"); lblSecurityQuestion.setValue(Msg.getMsg(m_ctx, "SecurityQuestion")); @@ -208,16 +225,19 @@ public class ResetPasswordPanel extends Window implements EventListener lblAnswer.setId("lblAnswer"); lblAnswer.setValue(Msg.getMsg(m_ctx, "Answer")); - lstSecurityQuestion = new Combobox(); - lstSecurityQuestion.setAutocomplete(true); - lstSecurityQuestion.setAutodrop(true); - lstSecurityQuestion.setId("lstSecurityQuestion"); - lstSecurityQuestion.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + lstSecurityQuestion.getId()); - lstSecurityQuestion.setWidth("220px"); + txtEmail = new Textbox(); + txtEmail.setId("txtEmail"); + txtEmail.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + txtEmail.getId()); + txtEmail.setCols(25); + txtEmail.setWidth("220px"); + txtEmail.setReadonly(false); - lstSecurityQuestion.getItems().clear(); - for (int i = 1; i <= NO_OF_SECURITY_QUESTION; i++) - lstSecurityQuestion.appendItem(Msg.getMsg(m_ctx, SECURITY_QUESTION_PREFIX + i), SECURITY_QUESTION_PREFIX + i); + txtSecurityQuestion = new Textbox(); + txtSecurityQuestion.setId("txtSecurityQuestion"); + txtSecurityQuestion.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + txtSecurityQuestion.getId()); + txtSecurityQuestion.setCols(25); + txtSecurityQuestion.setWidth("220px"); + txtSecurityQuestion.setReadonly(true); txtAnswer = new Textbox(); txtAnswer.setId("txtAnswer"); @@ -225,14 +245,49 @@ public class ResetPasswordPanel extends Window implements EventListener txtAnswer.setAttribute(AdempiereIdGenerator.ZK_COMPONENT_PREFIX_ATTRIBUTE, "unq" + txtAnswer.getId()); txtAnswer.setCols(25); txtAnswer.setWidth("220px"); + txtAnswer.setReadonly(true); } - } + } + + private void loadData() + { + boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false); + if (email_login) + { + txtEmail.setText(m_userName); + loadSecurityQuestion(); + } + } + + private void loadSecurityQuestion() + { + String email = txtEmail.getValue(); + if (Util.isEmpty(email)) + throw new IllegalArgumentException(Msg.getMsg(m_ctx, "FillMandatory") + " " + lblEmail.getValue()); + + // Assume user with same email uses the same password and security question + StringBuilder sql = new StringBuilder("SELECT SecurityQuestion "); + sql.append("FROM AD_User "); + sql.append("WHERE IsActive='Y' "); + sql.append("AND EMail=? "); + sql.append("AND SecurityQuestion IS NOT NULL "); + sql.append("ORDER BY AD_Client_ID DESC"); + + String securityQuestion = DB.getSQLValueString(null, sql.toString(), email); + txtSecurityQuestion.setValue(securityQuestion); + + txtEmail.setReadonly(true); + txtAnswer.setReadonly(false); + } public void onEvent(Event event) { if (event.getTarget().getId().equals(ConfirmPanel.A_OK)) { - validateResetPassword(); + if (txtAnswer.isReadonly()) + validateEmail(); + else + validateResetPassword(); } else if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL)) { @@ -241,7 +296,36 @@ public class ResetPasswordPanel extends Window implements EventListener } } - public void validateResetPassword() + private void validateEmail() + { + String email = txtEmail.getValue(); + if (Util.isEmpty(email)) + throw new IllegalArgumentException(Msg.getMsg(m_ctx, "FillMandatory") + " " + lblEmail.getValue()); + + StringBuilder whereClause = new StringBuilder("Password IS NOT NULL "); + whereClause.append("AND COALESCE(LDAPUser,Name)=? "); + whereClause.append("AND EMail=? "); + whereClause.append(" AND") + .append(" EXISTS (SELECT * FROM AD_User_Roles ur") + .append(" INNER JOIN AD_Role r ON (ur.AD_Role_ID=r.AD_Role_ID)") + .append(" WHERE ur.AD_User_ID=AD_User.AD_User_ID AND ur.IsActive='Y' AND r.IsActive='Y') AND ") + .append(" EXISTS (SELECT * FROM AD_Client c") + .append(" WHERE c.AD_Client_ID=AD_User.AD_Client_ID") + .append(" AND c.IsActive='Y') AND ") + .append(" AD_User.IsActive='Y'"); + + List users = new Query(m_ctx, MUser.Table_Name, whereClause.toString(), null) + .setParameters(m_userName, email) + .setOrderBy(MUser.COLUMNNAME_AD_User_ID) + .list(); + + if (users.size() == 0) + throw new AdempiereException(Msg.getMsg(m_ctx, "InvalidUserNameAndEmail")); + + loadSecurityQuestion(); + } + + private void validateResetPassword() { List users = null; if (m_noSecurityQuestion) @@ -278,10 +362,8 @@ public class ResetPasswordPanel extends Window implements EventListener } else { - String securityQuestion = null; - if (lstSecurityQuestion.getSelectedItem() != null) - securityQuestion = (String) lstSecurityQuestion.getSelectedItem().getValue(); - + String email = txtEmail.getValue(); + String securityQuestion = txtSecurityQuestion.getValue(); String answer = txtAnswer.getValue(); if (Util.isEmpty(securityQuestion)) @@ -290,12 +372,8 @@ public class ResetPasswordPanel extends Window implements EventListener if (Util.isEmpty(answer)) throw new IllegalArgumentException(Msg.getMsg(m_ctx, "AnswerMandatory")); - boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false); StringBuilder whereClause = new StringBuilder("Password IS NOT NULL AND "); - if (email_login) - whereClause.append("EMail=?"); - else - whereClause.append("COALESCE(LDAPUser,Name)=?"); + whereClause.append("EMail=?"); whereClause.append(" AND") .append(" EXISTS (SELECT * FROM AD_User_Roles ur") .append(" INNER JOIN AD_Role r ON (ur.AD_Role_ID=r.AD_Role_ID)") @@ -308,7 +386,7 @@ public class ResetPasswordPanel extends Window implements EventListener .append(" AND AD_User.Answer=?"); users = new Query(m_ctx, MUser.Table_Name, whereClause.toString(), null) - .setParameters(m_userName, securityQuestion, answer) + .setParameters(email, securityQuestion, answer) .setOrderBy(MUser.COLUMNNAME_AD_User_ID) .list(); } @@ -358,7 +436,7 @@ public class ResetPasswordPanel extends Window implements EventListener if (errorMsg.length() > 0) errorMsg += ", "; errorMsg += user.getEMail(); - throw new AdempiereException("Failed to send email to user - " + user.getEMail()); + throw new AdempiereException(Msg.getMsg(m_ctx, "RequestActionEMailError") + ": " + user.getEMail()); } }