From c1a1045d87688b3b17b684e68c4d7e9d10775bfc Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Tue, 4 Oct 2022 11:14:05 +0200 Subject: [PATCH] IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823) (#1498) * IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823) - Add column AD_Client.LoginPrefix * - Implement logic to manage login prefix - Add SysConfig keys LOGIN_PREFIX_SEPARATOR and LOGIN_WITH_TENANT_PREFIX * - Rename methods as suggested by Heng Sin * IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823) For security reasons is better to ask for MFA before showing additional information from the user. Refactoring the panels to show the MFA panel as soon as the tenant is defined. * - Add uniqueness validations on tenant creation * - Fix the Forgot My Password functionality * - Fix the Change Expired Password functionality * - minor javadoc improvement - remove a redundant comment, the method is already mark as deprecated Co-authored-by: hengsin --- .../oracle/202209221920_IDEMPIERE-5408.sql | 126 ++++++++++++++++++ .../202209221920_IDEMPIERE-5408.sql | 123 +++++++++++++++++ .../adempiere/process/InitialClientSetup.java | 12 +- .../src/org/compiere/model/I_AD_Client.java | 23 +++- .../src/org/compiere/model/MClient.java | 28 +++- .../src/org/compiere/model/MSetup.java | 2 + .../src/org/compiere/model/MSysConfig.java | 4 +- .../src/org/compiere/model/MSystem.java | 20 ++- .../src/org/compiere/model/X_AD_Client.java | 27 +++- .../src/org/compiere/util/Login.java | 72 +++++++++- .../webui/panel/ChangePasswordPanel.java | 5 +- .../org/adempiere/webui/panel/LoginPanel.java | 26 +++- .../org/adempiere/webui/panel/RolePanel.java | 55 ++++---- .../webui/panel/ValidateMFAPanel.java | 78 ++++------- .../adempiere/webui/window/LoginWindow.java | 100 +++++++++++--- 15 files changed, 574 insertions(+), 127 deletions(-) create mode 100644 migration/iD10/oracle/202209221920_IDEMPIERE-5408.sql create mode 100644 migration/iD10/postgresql/202209221920_IDEMPIERE-5408.sql diff --git a/migration/iD10/oracle/202209221920_IDEMPIERE-5408.sql b/migration/iD10/oracle/202209221920_IDEMPIERE-5408.sql new file mode 100644 index 0000000000..c41dc603f6 --- /dev/null +++ b/migration/iD10/oracle/202209221920_IDEMPIERE-5408.sql @@ -0,0 +1,126 @@ +-- IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823) +SELECT register_migration_script('202209221920_IDEMPIERE-5408.sql') FROM dual; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Sep 22, 2022, 7:20:41 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203679,0,0,'Y',TO_TIMESTAMP('2022-09-22 19:20:28','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-22 19:20:28','YYYY-MM-DD HH24:MI:SS'),100,'LoginPrefix','Login Prefix',NULL,NULL,'Login Prefix','D','2b343447-35fc-4aeb-865d-035d3e9dd74f') +; + +-- Sep 22, 2022, 7:21:50 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml,AD_InfoWindow_ID) VALUES (215385,0,'Login Prefix',112,'LoginPrefix',40,'N','N','N','N','N',0,'N',10,0,0,'Y',TO_TIMESTAMP('2022-09-22 19:21:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-22 19:21:49','YYYY-MM-DD HH24:MI:SS'),100,203679,'Y','N','D','N','N','N','Y','813befa6-0922-4583-b673-c965dbc925f8','Y',0,'N','N','N','N',200000) +; + +-- Sep 22, 2022, 7:22:04 PM CEST +ALTER TABLE AD_Client ADD LoginPrefix VARCHAR2(40 CHAR) DEFAULT NULL +; + +-- Sep 22, 2022, 7:22:50 PM CEST +INSERT INTO AD_TableIndex (AD_Client_ID,AD_Org_ID,AD_TableIndex_ID,AD_TableIndex_UU,Created,CreatedBy,EntityType,IsActive,Name,Updated,UpdatedBy,AD_Table_ID,IsCreateConstraint,IsUnique,Processing,IsKey) VALUES (0,0,201131,'3c2eaaa6-51d6-4f44-8652-bd904f70d1a8',TO_TIMESTAMP('2022-09-22 19:22:50','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','ad_client_loginprefix',TO_TIMESTAMP('2022-09-22 19:22:50','YYYY-MM-DD HH24:MI:SS'),100,112,'N','Y','N','N') +; + +-- Sep 22, 2022, 7:23:03 PM CEST +INSERT INTO AD_IndexColumn (AD_Client_ID,AD_Org_ID,AD_IndexColumn_ID,AD_IndexColumn_UU,Created,CreatedBy,EntityType,IsActive,Updated,UpdatedBy,AD_Column_ID,AD_TableIndex_ID,SeqNo) VALUES (0,0,201516,'5f8ecb6c-5116-40ec-bdc8-e1d9d9df5fbb',TO_TIMESTAMP('2022-09-22 19:23:03','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2022-09-22 19:23:03','YYYY-MM-DD HH24:MI:SS'),100,215385,201131,10) +; + +-- Sep 22, 2022, 7:23:14 PM CEST +CREATE UNIQUE INDEX ad_client_loginprefix ON AD_Client (LoginPrefix) +; + +-- Sep 22, 2022, 7:23:31 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207264,'Login Prefix',145,215385,'Y',40,240,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-09-22 19:23:31','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-22 19:23:31','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','79f147fc-77ac-4a37-bd49-ed05ea6461c4','Y',270,2) +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=20, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=4, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207264 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=30,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=317 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=40,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=318 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=50,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=319 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=60,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10318 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=70,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5160 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=80,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5759 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=90,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=11025 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=100,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=11205 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=110,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3813 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5887 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200594 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200595 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5161 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5162 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5163 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5164 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204476 +; + +-- Sep 23, 2022, 9:40:32 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200207,0,0,TO_TIMESTAMP('2022-09-23 21:40:32','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-09-23 21:40:32','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','LOGIN_PREFIX_SEPARATOR','/','Define the separator between tenant and user when using login prefix','D','S','401baee7-ed2b-4c46-89f9-93ba324411b7') +; + +-- Sep 23, 2022, 9:41:35 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200208,0,0,TO_TIMESTAMP('2022-09-23 21:41:35','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-09-23 21:41:35','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','LOGIN_WITH_TENANT_PREFIX','N','Accepted values are (N)o | (A)llow | (F)orce. WARNING: Before setting Force you must fill properly the login prefixes on all tenants.','D','S','9e5af823-d8c6-4019-8f0e-a6d894f3a9cb') +; + +-- Sep 23, 2022, 9:42:25 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Tenant not specified at login',0,0,'Y',TO_TIMESTAMP('2022-09-23 21:42:24','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-23 21:42:24','YYYY-MM-DD HH24:MI:SS'),100,200786,'MissingLoginTenant','D','073cb962-7666-4fa3-b471-ca9af693eb3a') +; + +-- Sep 23, 2022, 9:42:38 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','User not specified at login',0,0,'Y',TO_TIMESTAMP('2022-09-23 21:42:37','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-23 21:42:37','YYYY-MM-DD HH24:MI:SS'),100,200787,'MissingLoginUser','D','0ec843b3-1082-4fac-8dac-a75d0e2f0673') +; + +-- Sep 23, 2022, 9:42:46 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Tenant {0} not found',0,0,'Y',TO_TIMESTAMP('2022-09-23 21:42:46','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-23 21:42:46','YYYY-MM-DD HH24:MI:SS'),100,200788,'TenantNotFound','D','b806368b-55e7-4d5f-af17-5317c8eefd6c') +; + diff --git a/migration/iD10/postgresql/202209221920_IDEMPIERE-5408.sql b/migration/iD10/postgresql/202209221920_IDEMPIERE-5408.sql new file mode 100644 index 0000000000..bbd19952f3 --- /dev/null +++ b/migration/iD10/postgresql/202209221920_IDEMPIERE-5408.sql @@ -0,0 +1,123 @@ +-- IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823) +SELECT register_migration_script('202209221920_IDEMPIERE-5408.sql') FROM dual; + +-- Sep 22, 2022, 7:20:41 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,Help,PrintName,EntityType,AD_Element_UU) VALUES (203679,0,0,'Y',TO_TIMESTAMP('2022-09-22 19:20:28','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-22 19:20:28','YYYY-MM-DD HH24:MI:SS'),100,'LoginPrefix','Login Prefix',NULL,NULL,'Login Prefix','D','2b343447-35fc-4aeb-865d-035d3e9dd74f') +; + +-- Sep 22, 2022, 7:21:50 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml,AD_InfoWindow_ID) VALUES (215385,0,'Login Prefix',112,'LoginPrefix',40,'N','N','N','N','N',0,'N',10,0,0,'Y',TO_TIMESTAMP('2022-09-22 19:21:49','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-22 19:21:49','YYYY-MM-DD HH24:MI:SS'),100,203679,'Y','N','D','N','N','N','Y','813befa6-0922-4583-b673-c965dbc925f8','Y',0,'N','N','N','N',200000) +; + +-- Sep 22, 2022, 7:22:04 PM CEST +ALTER TABLE AD_Client ADD COLUMN LoginPrefix VARCHAR(40) DEFAULT NULL +; + +-- Sep 22, 2022, 7:22:50 PM CEST +INSERT INTO AD_TableIndex (AD_Client_ID,AD_Org_ID,AD_TableIndex_ID,AD_TableIndex_UU,Created,CreatedBy,EntityType,IsActive,Name,Updated,UpdatedBy,AD_Table_ID,IsCreateConstraint,IsUnique,Processing,IsKey) VALUES (0,0,201131,'3c2eaaa6-51d6-4f44-8652-bd904f70d1a8',TO_TIMESTAMP('2022-09-22 19:22:50','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','ad_client_loginprefix',TO_TIMESTAMP('2022-09-22 19:22:50','YYYY-MM-DD HH24:MI:SS'),100,112,'N','Y','N','N') +; + +-- Sep 22, 2022, 7:23:03 PM CEST +INSERT INTO AD_IndexColumn (AD_Client_ID,AD_Org_ID,AD_IndexColumn_ID,AD_IndexColumn_UU,Created,CreatedBy,EntityType,IsActive,Updated,UpdatedBy,AD_Column_ID,AD_TableIndex_ID,SeqNo) VALUES (0,0,201516,'5f8ecb6c-5116-40ec-bdc8-e1d9d9df5fbb',TO_TIMESTAMP('2022-09-22 19:23:03','YYYY-MM-DD HH24:MI:SS'),100,'D','Y',TO_TIMESTAMP('2022-09-22 19:23:03','YYYY-MM-DD HH24:MI:SS'),100,215385,201131,10) +; + +-- Sep 22, 2022, 7:23:14 PM CEST +CREATE UNIQUE INDEX ad_client_loginprefix ON AD_Client (LoginPrefix) +; + +-- Sep 22, 2022, 7:23:31 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207264,'Login Prefix',145,215385,'Y',40,240,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2022-09-22 19:23:31','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-22 19:23:31','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','79f147fc-77ac-4a37-bd49-ed05ea6461c4','Y',270,2) +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET IsDisplayed='Y', SeqNo=20, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=4, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207264 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=30,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=317 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=40,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=318 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=50,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=319 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=60,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10318 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=70,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5160 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=80,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5759 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=90,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=11025 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=100,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=11205 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=110,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3813 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=120,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5887 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200594 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200595 +; + +-- Sep 22, 2022, 7:24:07 PM CEST +UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2022-09-22 19:24:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5161 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5162 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5163 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5164 +; + +-- Sep 22, 2022, 7:24:08 PM CEST +UPDATE AD_Field SET SeqNo=0,Updated=TO_TIMESTAMP('2022-09-22 19:24:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204476 +; + +-- Sep 23, 2022, 9:40:32 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200207,0,0,TO_TIMESTAMP('2022-09-23 21:40:32','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-09-23 21:40:32','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','LOGIN_PREFIX_SEPARATOR','/','Define the separator between tenant and user when using login prefix','D','S','401baee7-ed2b-4c46-89f9-93ba324411b7') +; + +-- Sep 23, 2022, 9:41:35 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200208,0,0,TO_TIMESTAMP('2022-09-23 21:41:35','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-09-23 21:41:35','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','LOGIN_WITH_TENANT_PREFIX','N','Accepted values are (N)o | (A)llow | (F)orce. WARNING: Before setting Force you must fill properly the login prefixes on all tenants.','D','S','9e5af823-d8c6-4019-8f0e-a6d894f3a9cb') +; + +-- Sep 23, 2022, 9:42:25 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Tenant not specified at login',0,0,'Y',TO_TIMESTAMP('2022-09-23 21:42:24','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-23 21:42:24','YYYY-MM-DD HH24:MI:SS'),100,200786,'MissingLoginTenant','D','073cb962-7666-4fa3-b471-ca9af693eb3a') +; + +-- Sep 23, 2022, 9:42:38 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','User not specified at login',0,0,'Y',TO_TIMESTAMP('2022-09-23 21:42:37','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-23 21:42:37','YYYY-MM-DD HH24:MI:SS'),100,200787,'MissingLoginUser','D','0ec843b3-1082-4fac-8dac-a75d0e2f0673') +; + +-- Sep 23, 2022, 9:42:46 PM CEST +INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Tenant {0} not found',0,0,'Y',TO_TIMESTAMP('2022-09-23 21:42:46','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-09-23 21:42:46','YYYY-MM-DD HH24:MI:SS'),100,200788,'TenantNotFound','D','b806368b-55e7-4d5f-af17-5317c8eefd6c') +; + diff --git a/org.adempiere.base.process/src/org/adempiere/process/InitialClientSetup.java b/org.adempiere.base.process/src/org/adempiere/process/InitialClientSetup.java index 318aac7502..2288959bcf 100644 --- a/org.adempiere.base.process/src/org/adempiere/process/InitialClientSetup.java +++ b/org.adempiere.base.process/src/org/adempiere/process/InitialClientSetup.java @@ -216,13 +216,19 @@ public class InitialClientSetup extends SvrProcess // Validate Uniqueness of client and users name // Unique Client Name - if (DB.executeUpdate("UPDATE AD_Client SET CreatedBy=0 WHERE Name=?", new Object[] {p_ClientName}, false, null) != 0) + if (DB.getSQLValueEx(null, "SELECT COUNT(*) FROM AD_Client WHERE Name=?", p_ClientName) != 0) throw new AdempiereException(Msg.parseTranslation(getCtx(), "@NotUnique@ @ClientName@ = " + p_ClientName)); + if (DB.getSQLValueEx(null, "SELECT COUNT(*) FROM AD_Client WHERE Value=?", p_ClientName) != 0) + throw new AdempiereException(Msg.parseTranslation(getCtx(), "@NotUnique@ @ClientValue@ = " + p_ClientName)); + + if (DB.getSQLValueEx(null, "SELECT COUNT(*) FROM AD_Client WHERE LoginPrefix=?", p_ClientName) != 0) + throw new AdempiereException(Msg.parseTranslation(getCtx(), "@NotUnique@ @LoginPrefix@ = " + p_ClientName)); + // Unique User Names - if (DB.executeUpdate("UPDATE AD_User SET CreatedBy=0 WHERE Name=?", new Object[] {p_AdminUserName}, false, null) != 0) + if (DB.getSQLValueEx(null, "SELECT COUNT(*) FROM AD_User WHERE Name=?", p_AdminUserName) != 0) throw new AdempiereException(Msg.parseTranslation(getCtx(), "@NotUnique@ @AdminUserName@ = " + p_AdminUserName)); - if (DB.executeUpdate("UPDATE AD_User SET CreatedBy=0 WHERE Name=?", new Object[] {p_NormalUserName}, false, null) != 0) + if (DB.getSQLValueEx(null, "SELECT COUNT(*) FROM AD_User WHERE Name=?", p_NormalUserName) != 0) throw new AdempiereException(Msg.parseTranslation(getCtx(), "@NotUnique@ @NormalUserName@ = " + p_NormalUserName)); // City_ID overrides CityName if both used diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_Client.java b/org.adempiere.base/src/org/compiere/model/I_AD_Client.java index d33df27637..07346734ff 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_Client.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_Client.java @@ -22,7 +22,7 @@ import org.compiere.util.KeyNamePair; /** Generated Interface for AD_Client * @author iDempiere (generated) - * @version Release 9 + * @version Release 10 */ public interface I_AD_Client { @@ -44,8 +44,8 @@ public interface I_AD_Client /** Column name AD_Client_ID */ public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID"; - /** Get Client. - * Client/Tenant for this installation. + /** Get Tenant. + * Tenant for this installation. */ public int getAD_Client_ID(); @@ -75,12 +75,12 @@ public interface I_AD_Client public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID"; /** Set Organization. - * Organizational entity within client + * Organizational entity within tenant */ public void setAD_Org_ID (int AD_Org_ID); /** Get Organization. - * Organizational entity within client + * Organizational entity within tenant */ public int getAD_Org_ID(); @@ -246,10 +246,10 @@ public interface I_AD_Client /** Column name IsUseASP */ public static final String COLUMNNAME_IsUseASP = "IsUseASP"; - /** Set IsUseASP */ + /** Set Is Use ASP */ public void setIsUseASP (boolean IsUseASP); - /** Get IsUseASP */ + /** Get Is Use ASP */ public boolean isUseASP(); /** Column name IsUseBetaFunctions */ @@ -265,6 +265,15 @@ public interface I_AD_Client */ public boolean isUseBetaFunctions(); + /** Column name LoginPrefix */ + public static final String COLUMNNAME_LoginPrefix = "LoginPrefix"; + + /** Set Login Prefix */ + public void setLoginPrefix (String LoginPrefix); + + /** Get Login Prefix */ + public String getLoginPrefix(); + /** Column name MMPolicy */ public static final String COLUMNNAME_MMPolicy = "MMPolicy"; diff --git a/org.adempiere.base/src/org/compiere/model/MClient.java b/org.adempiere.base/src/org/compiere/model/MClient.java index 70baee8b09..77257c3fe4 100644 --- a/org.adempiere.base/src/org/compiere/model/MClient.java +++ b/org.adempiere.base/src/org/compiere/model/MClient.java @@ -53,11 +53,11 @@ import org.idempiere.cache.ImmutablePOSupport; *
  • BF [ 1886480 ] Print Format Item Trl not updated even if not multilingual */ public class MClient extends X_AD_Client implements ImmutablePOSupport -{ +{ /** * */ - private static final long serialVersionUID = 1820358079361924020L; + private static final long serialVersionUID = 2479547777642328967L; /** * Get client from cache (immutable) @@ -121,6 +121,30 @@ public class MClient extends X_AD_Client implements ImmutablePOSupport return retValue; } // getAll + /** + * Get a MClient object based on LoginPrefix + * @param loginPrefix + * @return MClient + */ + public static MClient getByLoginPrefix(String loginPrefix) { + MClient client = null; + try { + PO.setCrossTenantSafe(); + client = new Query(Env.getCtx(), Table_Name, "LoginPrefix=?", (String)null) + .setOnlyActiveRecords(true) + .setParameters(loginPrefix) + .first(); + } finally { + PO.clearCrossTenantSafe(); + } + if (client != null ) { + Integer key = Integer.valueOf(client.getAD_Client_ID()); + if (! s_cache.containsKey(key)) + s_cache.put (Integer.valueOf(client.getAD_Client_ID()), client, e -> new MClient(Env.getCtx(), e)); + } + return client; + } + /** * Get optionally cached client * @param ctx context diff --git a/org.adempiere.base/src/org/compiere/model/MSetup.java b/org.adempiere.base/src/org/compiere/model/MSetup.java index 22dfaefbc8..0ac731d5a9 100644 --- a/org.adempiere.base/src/org/compiere/model/MSetup.java +++ b/org.adempiere.base/src/org/compiere/model/MSetup.java @@ -146,6 +146,8 @@ public final class MSetup m_clientName = name; m_client = new MClient(m_ctx, 0, true, m_trx.getTrxName()); m_client.setValue(m_clientName); + if (MSystem.isUseLoginPrefix()) + m_client.setLoginPrefix(m_clientName); m_client.setName(m_clientName); if (!m_client.save()) { diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index 73267ad944..4e029b5b65 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -44,7 +44,7 @@ public class MSysConfig extends X_AD_SysConfig /** * */ - private static final long serialVersionUID = 4367630918820342645L; + private static final long serialVersionUID = -5704354666566021353L; public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION"; public static final String ALERT_SEND_ATTACHMENT_AS_XLS = "ALERT_SEND_ATTACHMENT_AS_XLS"; @@ -122,7 +122,9 @@ public class MSysConfig extends X_AD_SysConfig public static final String LOCATION_MAPS_URL_PREFIX = "LOCATION_MAPS_URL_PREFIX"; public static final String LOCATION_MAX_CITY_ROWS = "LOCATION_MAX_CITY_ROWS"; public static final String LOGIN_HELP_URL = "LOGIN_HELP_URL"; + public static final String LOGIN_PREFIX_SEPARATOR = "LOGIN_PREFIX_SEPARATOR"; public static final String LOGIN_SHOW_RESETPASSWORD = "LOGIN_SHOW_RESETPASSWORD"; + public static final String LOGIN_WITH_TENANT_PREFIX = "LOGIN_WITH_TENANT_PREFIX"; public static final String MAIL_DONT_SEND_TO_ADDRESS = "MAIL_DONT_SEND_TO_ADDRESS"; public static final String MAIL_SEND_BCC_TO_ADDRESS = "MAIL_SEND_BCC_TO_ADDRESS"; public static final String MAIL_SEND_BCC_TO_FROM = "MAIL_SEND_BCC_TO_FROM"; diff --git a/org.adempiere.base/src/org/compiere/model/MSystem.java b/org.adempiere.base/src/org/compiere/model/MSystem.java index f09d535cac..ade566dd9e 100644 --- a/org.adempiere.base/src/org/compiere/model/MSystem.java +++ b/org.adempiere.base/src/org/compiere/model/MSystem.java @@ -56,7 +56,7 @@ public class MSystem extends X_AD_System /** * */ - private static final long serialVersionUID = 3090872841676580202L; + private static final long serialVersionUID = -1917493005917422880L; /** * Load System Record @@ -521,4 +521,22 @@ public class MSystem extends X_AD_System return true; } + /** + * The system allows to use login prefix for tenant + * @return + */ + public static boolean isUseLoginPrefix() { + String loginWithTenantPrefix = MSysConfig.getValue(MSysConfig.LOGIN_WITH_TENANT_PREFIX, "N"); + return "F".equals(loginWithTenantPrefix) || "A".equals(loginWithTenantPrefix); + } + + /** + * The system forces to use login prefix for tenant + * @return + */ + public static boolean isLoginPrefixMandatory() { + String loginWithTenantPrefix = MSysConfig.getValue(MSysConfig.LOGIN_WITH_TENANT_PREFIX, "N"); + return "F".equals(loginWithTenantPrefix); + } + } // MSystem diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_Client.java b/org.adempiere.base/src/org/compiere/model/X_AD_Client.java index aba218ab3d..5a6a9e7d8a 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_Client.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_Client.java @@ -23,7 +23,7 @@ import org.compiere.util.KeyNamePair; /** Generated Model for AD_Client * @author iDempiere (generated) - * @version Release 9 - $Id$ */ + * @version Release 10 - $Id$ */ @org.adempiere.base.Model(table="AD_Client") public class X_AD_Client extends PO implements I_AD_Client, I_Persistent { @@ -31,7 +31,7 @@ public class X_AD_Client extends PO implements I_AD_Client, I_Persistent /** * */ - private static final long serialVersionUID = 20220116L; + private static final long serialVersionUID = 20220922L; /** Standard Constructor */ public X_AD_Client (Properties ctx, int AD_Client_ID, String trxName) @@ -369,16 +369,16 @@ public class X_AD_Client extends PO implements I_AD_Client, I_Persistent return false; } - /** Set IsUseASP. - @param IsUseASP IsUseASP + /** Set Is Use ASP. + @param IsUseASP Is Use ASP */ public void setIsUseASP (boolean IsUseASP) { set_Value (COLUMNNAME_IsUseASP, Boolean.valueOf(IsUseASP)); } - /** Get IsUseASP. - @return IsUseASP */ + /** Get Is Use ASP. + @return Is Use ASP */ public boolean isUseASP() { Object oo = get_Value(COLUMNNAME_IsUseASP); @@ -414,6 +414,21 @@ public class X_AD_Client extends PO implements I_AD_Client, I_Persistent return false; } + /** Set Login Prefix. + @param LoginPrefix Login Prefix + */ + public void setLoginPrefix (String LoginPrefix) + { + set_Value (COLUMNNAME_LoginPrefix, LoginPrefix); + } + + /** Get Login Prefix. + @return Login Prefix */ + public String getLoginPrefix() + { + return (String)get_Value(COLUMNNAME_LoginPrefix); + } + /** MMPolicy AD_Reference_ID=335 */ public static final int MMPOLICY_AD_Reference_ID=335; /** FiFo = F */ diff --git a/org.adempiere.base/src/org/compiere/util/Login.java b/org.adempiere.base/src/org/compiere/util/Login.java index a42fa0619d..ce43e6517e 100644 --- a/org.adempiere.base/src/org/compiere/util/Login.java +++ b/org.adempiere.base/src/org/compiere/util/Login.java @@ -36,6 +36,7 @@ import org.compiere.Adempiere; import org.compiere.db.CConnection; import org.compiere.model.I_M_Warehouse; import org.compiere.model.MAcctSchema; +import org.compiere.model.MClient; import org.compiere.model.MClientInfo; import org.compiere.model.MCountry; import org.compiere.model.MMFARegisteredDevice; @@ -176,6 +177,7 @@ public class Login * The error (NoDatabase, UserPwdError, DBLogin) is saved in the log * @deprecated */ + @Deprecated(since = "2", forRemoval = true) protected KeyNamePair[] getRoles (CConnection cc, String app_user, String app_pwd, boolean force) { @@ -210,8 +212,9 @@ public class Login * @param app_user Principal * @return role array or null if in error. * The error (NoDatabase, UserPwdError, DBLogin) is saved in the log - * @deprecated use public KeyNamePair[] getRoles(String app_user, KeyNamePair client) + * @deprecated use {@link #getRoles(String, KeyNamePair)} */ + @Deprecated(since = "2", forRemoval = true) public KeyNamePair[] getRoles (Principal app_user) { if (app_user == null) @@ -230,8 +233,9 @@ public class Login * @param app_pwd password * @return role array or null if in error. * The error (NoDatabase, UserPwdError, DBLogin) is saved in the log - * @deprecated use public KeyNamePair[] getRoles(String app_user, KeyNamePair client) + * @deprecated use use {@link #getRoles(String, KeyNamePair)} */ + @Deprecated(since = "2", forRemoval = true) public KeyNamePair[] getRoles (String app_user, String app_pwd) { return getRoles (app_user, app_pwd, false); @@ -244,8 +248,9 @@ public class Login * @param force ignore pwd * @return role array or null if in error. * The error (NoDatabase, UserPwdError, DBLogin) is saved in the log - * @deprecated use public KeyNamePair[] getRoles(String app_user, KeyNamePair client) + * @deprecated use {@link #getRoles(String, KeyNamePair)} */ + @Deprecated(since = "2", forRemoval = true) private KeyNamePair[] getRoles (String app_user, String app_pwd, boolean force) { if (log.isLoggable(Level.INFO)) log.info("User=" + app_user); @@ -1288,6 +1293,28 @@ public class Login // if not authenticated, use AD_User as backup (just for non-LDAP users) } + MClient client = null; + if (MSystem.isUseLoginPrefix()) { + String app_tenant = Login.getAppTenant(app_user); + app_user = Login.getAppUser(app_user); + boolean hasTenant = ! Util.isEmpty(app_tenant, true); + if (MSystem.isLoginPrefixMandatory() && ! hasTenant) { + loginErrMsg = Msg.getMsg(m_ctx, "MissingLoginTenant"); + return null; + } + if (Util.isEmpty(app_user, true)) { + loginErrMsg = Msg.getMsg(m_ctx, "MissingLoginUser"); + return null; + } + if (hasTenant) { + client = MClient.getByLoginPrefix(app_tenant); + if (client == null) { + loginErrMsg = Msg.getMsg(m_ctx, "TenantNotFound", new Object[] {app_tenant}); + return null; + } + } + } + boolean hash_password = MSysConfig.getBooleanValue(MSysConfig.USER_PASSWORD_HASH, false); boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false); KeyNamePair[] retValue = null; @@ -1312,7 +1339,8 @@ public class Login .append(" WHERE c.AD_Client_ID=AD_User.AD_Client_ID") .append(" AND c.IsActive='Y') AND ") .append(" AD_User.IsActive='Y'"); - + if (client != null) + where.append(" AND AD_Client_ID IN (0,").append(client.getAD_Client_ID()).append(")"); List users = null; try { PO.setCrossTenantSafe(); @@ -1428,6 +1456,8 @@ public class Login .append(" WHERE ur.IsActive='Y'") .append(" AND u.IsActive='Y'") .append(" AND cli.IsActive='Y'"); + if (client != null) + sql.append(" AND r.AD_Client_ID=").append(client.getAD_Client_ID()); if (! Util.isEmpty(whereRoleType)) { sql.append(" AND ").append(whereRoleType); } @@ -1543,6 +1573,38 @@ public class Login return retValue; } + /** + * Get the tenant from the login text when using login prefix + * @param app_user + * @return + */ + private static String getAppTenant(String app_user) { + String appTenant = null; + if (MSystem.isUseLoginPrefix()) { + String separator = MSysConfig.getValue(MSysConfig.LOGIN_PREFIX_SEPARATOR, "/"); + int idxSep = app_user.indexOf(separator); + if (idxSep >= 0) + appTenant = app_user.substring(0, idxSep); + } + return appTenant; + } + + /** + * Get the user from the login text + * @param app_user + * @return + */ + public static String getAppUser(String app_user) { + String appUser = app_user; + if (MSystem.isUseLoginPrefix()) { + String separator = MSysConfig.getValue(MSysConfig.LOGIN_PREFIX_SEPARATOR, "/"); + int idxSep = app_user.indexOf(separator); + if (idxSep >= 0) + appUser = app_user.substring(idxSep + 1); + } + return appUser; + } + public KeyNamePair[] getRoles(String app_user, KeyNamePair client) { return getRoles(app_user, client, null); } @@ -1593,7 +1655,7 @@ public class Login { pstmt = DB.prepareStatement(sql.toString(), null); pstmt.setInt(1, client.getKey()); - pstmt.setString(2, app_user); + pstmt.setString(2, getAppUser(app_user)); rs = pstmt.executeQuery(); if (!rs.next()) 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 e1d77e4a42..5d46ff37b5 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 @@ -41,6 +41,7 @@ import org.compiere.model.PO; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; +import org.compiere.util.Login; import org.compiere.util.Msg; import org.compiere.util.Trx; import org.compiere.util.Util; @@ -284,7 +285,7 @@ public class ChangePasswordPanel extends Window implements EventListener MPasswordRule pwdrule = MPasswordRule.getRules(Env.getCtx(), null); if (pwdrule != null) { try { - pwdrule.validate(m_userName, txtNewPassword.getValue(), new ArrayList()); + pwdrule.validate(Login.getAppUser(m_userName), txtNewPassword.getValue(), new ArrayList()); } catch (Exception e) { throw new WrongValueException(txtNewPassword, e.getMessage()); @@ -346,7 +347,7 @@ public class ChangePasswordPanel extends Window implements EventListener { int clientId = clientKNPair.getKey(); Env.setContext(m_ctx, Env.AD_CLIENT_ID, clientId); - MUser user = MUser.get(m_ctx, m_userName); + MUser user = MUser.get(m_ctx, Login.getAppUser(m_userName)); if (user == null) { trx.rollback(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java index dc790c2af3..aad1f6c0c4 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java @@ -102,7 +102,7 @@ public class LoginPanel extends Window implements EventListener /** * */ - private static final long serialVersionUID = -6130436148212949636L; + private static final long serialVersionUID = -7859522563172088496L; public static final String ROLE_TYPES_WEBUI = "NULL,ZK,SS"; //webui,support+null @@ -173,15 +173,24 @@ public class LoginPanel extends Window implements EventListener { onUserIdChange(AD_User_ID); if (MSystem.isZKRememberUserAllowed()) { + String fillUser = null; if (email_login) { - txtUserId.setValue(user.getEMail()); + fillUser = user.getEMail(); } else { if (user.getLDAPUser() != null && user.getLDAPUser().length() > 0) { - txtUserId.setValue(user.getLDAPUser()); + fillUser = user.getLDAPUser(); } else { - txtUserId.setValue(user.getName()); + fillUser = user.getName(); } } + if (MSystem.isUseLoginPrefix()) { + MClient client = MClient.get(session.getAD_Client_ID()); + if (! Util.isEmpty(client.getLoginPrefix())) { + String separator = MSysConfig.getValue(MSysConfig.LOGIN_PREFIX_SEPARATOR, "/"); + fillUser = client.getLoginPrefix() + separator + fillUser; + } + } + txtUserId.setValue(fillUser); chkRememberMe.setChecked(true); } if (MSystem.isZKRememberPasswordAllowed()) { @@ -606,6 +615,13 @@ public class LoginPanel extends Window implements EventListener } else { + if (clientsKNPairs.length == 1) { + Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, (String) clientsKNPairs[0].getID()); + MUser user = MUser.get(Env.getCtx(), Login.getAppUser(userId)); + if (user != null) + Env.setContext(Env.getCtx(), Env.AD_USER_ID, user.getAD_User_ID() ); + } + String langName = null; if ( lstLanguage.getSelectedItem() != null ) langName = (String) lstLanguage.getSelectedItem().getLabel(); @@ -667,7 +683,7 @@ public class LoginPanel extends Window implements EventListener private void btnResetPasswordClicked() { - String userId = txtUserId.getValue(); + String userId = Login.getAppUser(txtUserId.getValue()); if (Util.isEmpty(userId)) throw new IllegalArgumentException(Msg.getMsg(ctx, "FillMandatory") + " " + lblUserId.getValue()); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java index cf9464cf90..c674d4dee7 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java @@ -80,7 +80,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl /** * */ - private static final long serialVersionUID = -618446343598384819L; + private static final long serialVersionUID = -1159253307008488232L; protected LoginWindow wndLogin; protected Login login; @@ -98,12 +98,14 @@ public class RolePanel extends Window implements EventListener, Deferrabl protected UserPreference m_userpreference=null; - protected boolean m_show = true; + protected boolean m_showRolePanel = true; private RolePanel component; private boolean isChangeRole = false; + private boolean m_isClientDefined; + public boolean isChangeRole() { return isChangeRole; } @@ -117,17 +119,18 @@ public class RolePanel extends Window implements EventListener, Deferrabl private static final String ON_DEFER_LOGOUT = "onDeferLogout"; - public RolePanel(Properties ctx, LoginWindow loginWindow, String userName, boolean show, KeyNamePair[] clientsKNPairs) { + public RolePanel(Properties ctx, LoginWindow loginWindow, String userName, boolean show, KeyNamePair[] clientsKNPairs, boolean isClientDefined) { this.wndLogin = loginWindow; m_ctx = ctx; m_userName = userName; login = new Login(ctx); - m_show = show; + m_showRolePanel = show; + m_isClientDefined = isClientDefined; m_clientKNPairs = clientsKNPairs; - if( m_clientKNPairs.length == 1 && !m_show ){ + if( m_clientKNPairs.length == 1 && !m_showRolePanel ){ Env.setContext(m_ctx, Env.AD_CLIENT_ID, (String) m_clientKNPairs[0].getID()); - MUser user = MUser.get (m_ctx, m_userName); + MUser user = MUser.get (m_ctx, Login.getAppUser(m_userName)); m_userpreference=new UserPreference(); m_userpreference.loadPreference(user.get_ID()); } @@ -138,15 +141,15 @@ public class RolePanel extends Window implements EventListener, Deferrabl this.setId("rolePanel"); this.setSclass("login-box"); - if (! m_show) { + if (! m_showRolePanel) { // check if all mandatory fields are ok to not show if ( lstRole.getSelectedItem() == null || lstRole.getSelectedItem().getValue() == null || lstClient.getSelectedItem() == null || lstClient.getSelectedItem().getValue() == null || lstOrganisation.getSelectedItem() == null || lstOrganisation.getSelectedItem().getValue() == null) { - m_show = true; + m_showRolePanel = true; } } - if (m_show) { + if (m_showRolePanel) { AuFocus auf = null; if (lstClient.getItemCount() > 1) { auf = new AuFocus(lstClient); @@ -156,8 +159,6 @@ public class RolePanel extends Window implements EventListener, Deferrabl auf = new AuFocus(lstOrganisation); } Clients.response(auf); - } else { - validateRoles(); } } @@ -348,7 +349,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl // initial client - Elaine 2009/02/06 UserPreference userPreference = SessionManager.getSessionApplication().getUserPreference(); String initDefault = userPreference.getProperty(UserPreference.P_CLIENT); - if( initDefault.length() == 0 && !m_show && m_userpreference != null ) + if( initDefault.length() == 0 && !m_showRolePanel && m_userpreference != null ) { initDefault=m_userpreference.getProperty( UserPreference.P_CLIENT ); } @@ -365,7 +366,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl lstClient.setSelectedItem(ci); } if (lstClient.getSelectedIndex() == -1 && lstClient.getItemCount() > 0) { - m_show = true; // didn't find default client + m_showRolePanel = true; // didn't find default client lstClient.setSelectedIndex(0); } } @@ -402,7 +403,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl // initial role UserPreference userPreference = SessionManager.getSessionApplication().getUserPreference(); String initDefault = userPreference.getProperty(UserPreference.P_ROLE); - if( initDefault.length() == 0 && !m_show && m_userpreference != null ) + if( initDefault.length() == 0 && !m_showRolePanel && m_userpreference != null ) { initDefault=m_userpreference.getProperty( UserPreference.P_ROLE ); } @@ -422,7 +423,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl lstRole.setSelectedItem(ci); } if (lstRole.getSelectedIndex() == -1 && lstRole.getItemCount() > 0) { - m_show = true; // didn't find default role + m_showRolePanel = true; // didn't find default role lstRole.setSelectedIndex(0); } } @@ -451,7 +452,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl // initial organisation - Elaine 2009/02/06 UserPreference userPreference = SessionManager.getSessionApplication().getUserPreference(); String initDefault = userPreference.getProperty(UserPreference.P_ORG); - if( initDefault.length() == 0 && !m_show && m_userpreference != null ) + if( initDefault.length() == 0 && !m_showRolePanel && m_userpreference != null ) { initDefault=m_userpreference.getProperty( UserPreference.P_ORG ); } @@ -471,7 +472,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl } if (lstOrganisation.getSelectedIndex() == -1 && lstOrganisation.getItemCount() > 0) { - m_show = true; // didn't find default organisation + m_showRolePanel = true; // didn't find default organisation lstOrganisation.setSelectedIndex(0); } } @@ -499,7 +500,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl // initial warehouse - Elaine 2009/02/06 UserPreference userPreference = SessionManager.getSessionApplication().getUserPreference(); String initDefault = userPreference.getProperty(UserPreference.P_WAREHOUSE); - if( initDefault.length() == 0 && !m_show && m_userpreference != null ) + if( initDefault.length() == 0 && !m_showRolePanel && m_userpreference != null ) { initDefault=m_userpreference.getProperty( UserPreference.P_WAREHOUSE ); } @@ -516,7 +517,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl lstWarehouse.setSelectedItem(ci); } if (lstWarehouse.getSelectedIndex() == -1 && lstWarehouse.getItemCount() > 0) { - m_show = true; // didn't find default warehouse + m_showRolePanel = true; // didn't find default warehouse lstWarehouse.setSelectedIndex(0); } } @@ -542,13 +543,13 @@ public class RolePanel extends Window implements EventListener, Deferrabl } if (event.getTarget().getId().equals(ConfirmPanel.A_OK)) { - validateRoles(); + validateRoles(false); } else if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL)) { if (isChangeRole()) { changeRole(ctxBeforeChangeRole); - validateRoles(); + validateRoles(false); } else { ctxBeforeChangeRole = null; SessionManager.logoutSession(); @@ -568,7 +569,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl } else { Env.setContext(m_ctx, Env.AD_CLIENT_ID, (String) null); } - MUser user = MUser.get (m_ctx, m_userName); + MUser user = MUser.get (m_ctx, Login.getAppUser(m_userName)); if (user != null) { Env.setContext(m_ctx, Env.AD_USER_ID, user.getAD_User_ID() ); Env.setContext(m_ctx, Env.AD_USER_NAME, user.getName() ); @@ -598,9 +599,10 @@ public class RolePanel extends Window implements EventListener, Deferrabl /** * validate Roles + * @param isMFAValidated * **/ - public void validateRoles() + public void validateRoles(boolean isMFAValidated) { Clients.clearBusy(); Comboitem lstItemRole = lstRole.getSelectedItem(); @@ -660,7 +662,10 @@ public class RolePanel extends Window implements EventListener, Deferrabl MRole.getDefault(m_ctx, true); // - wndLogin.validateMFA(orgKNPair); + if (m_isClientDefined || isMFAValidated) + wndLogin.loginCompleted(login, orgKNPair, this); + else + wndLogin.validateMFA(orgKNPair, m_isClientDefined, m_userName, m_showRolePanel, m_clientKNPairs); } public boolean isDeferrable() { @@ -668,6 +673,6 @@ public class RolePanel extends Window implements EventListener, Deferrabl } public boolean show() { - return m_show; + return m_showRolePanel; } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ValidateMFAPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ValidateMFAPanel.java index 47a34992f5..7614299e3d 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ValidateMFAPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/ValidateMFAPanel.java @@ -34,9 +34,7 @@ import java.util.logging.Level; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import org.adempiere.util.Callback; import org.adempiere.util.LogAuthFailure; import org.adempiere.webui.AdempiereIdGenerator; import org.adempiere.webui.LayoutUtils; @@ -50,7 +48,6 @@ import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.ZKUpdateUtil; -import org.adempiere.webui.window.Dialog; import org.adempiere.webui.window.LoginWindow; import org.compiere.model.MMFAMethod; import org.compiere.model.MMFARegisteredDevice; @@ -63,7 +60,6 @@ import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Login; import org.compiere.util.Msg; -import org.compiere.util.TimeUtil; import org.compiere.util.Util; import org.zkoss.zhtml.Div; import org.zkoss.zhtml.Table; @@ -71,11 +67,9 @@ import org.zkoss.zhtml.Td; import org.zkoss.zhtml.Tr; import org.zkoss.zk.au.out.AuFocus; import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; -import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Checkbox; import org.zkoss.zul.Image; @@ -84,21 +78,16 @@ public class ValidateMFAPanel extends Window implements EventListener { /** * */ - private static final long serialVersionUID = -2347409338340527333L; + private static final long serialVersionUID = 4777197666886479162L; private static final CLogger logger = CLogger.getCLogger(ValidateMFAPanel.class); - private static final String ON_DEFER_LOGOUT = "onDeferLogout"; - protected LoginWindow wndLogin; protected Login login; - private ValidateMFAPanel component; /** Context */ protected Properties m_ctx; - protected boolean m_show = true; - protected Label lblMFAMechanism; protected Combobox lstMFAMechanism; protected Label lblMFAMsg; @@ -108,6 +97,12 @@ public class ValidateMFAPanel extends Window implements EventListener { protected Checkbox chkRegisterDevice = null; private KeyNamePair m_orgKNPair; + private KeyNamePair[] m_clientsKNPairs; + + private boolean m_isClientDefined; + private String m_userName; + private boolean m_showRolePanel = true; + private boolean m_showMFAPanel = false; /* Push the first OK automatically - when the first record is TOTP */ private boolean m_autoCall = false; @@ -117,15 +112,17 @@ public class ValidateMFAPanel extends Window implements EventListener { /* Number of failures to calculate an incremental delay on every trial */ private int failures = 0; - public ValidateMFAPanel(Properties ctx, LoginWindow loginWindow, KeyNamePair orgKNPair) { + public ValidateMFAPanel(Properties ctx, LoginWindow loginWindow, KeyNamePair orgKNPair, boolean isClientDefined, String userName, boolean showRolePanel, KeyNamePair[] clientsKNPairs) { this.wndLogin = loginWindow; m_ctx = ctx; this.m_orgKNPair = orgKNPair; - this.component = this; + m_isClientDefined = isClientDefined; + m_userName = userName; + m_showRolePanel = showRolePanel; + m_clientsKNPairs = clientsKNPairs; String registerCookie = getCookie(getCookieName()); login = new Login(ctx); - this.addEventListener(ON_DEFER_LOGOUT, this); if (login.isMFARequired(registerCookie)) { initComponents(registerCookie != null); init(); @@ -301,8 +298,6 @@ public class ValidateMFAPanel extends Window implements EventListener { validateMFAComplete(true); } else if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL)) { SessionManager.logoutSession(); - } else if (ON_DEFER_LOGOUT.equals(event.getName())) { - SessionManager.logoutSession(); } } @@ -315,6 +310,7 @@ public class ValidateMFAPanel extends Window implements EventListener { boolean enablePreferred = (lstMFAMechanism.getChildren().size() > 1 && lstMFAMechanism.getSelectedIndex() > 0); chkSetPreferred.setVisible(enablePreferred); MMFARegistration reg = new MMFARegistration(Env.getCtx(), registrationId, null); + m_showMFAPanel = true; if (txtValidationCode.isDisabled()) { String msg = reg.generateValidationCode(reg); lblMFAMsg.setValue(msg); @@ -375,42 +371,16 @@ public class ValidateMFAPanel extends Window implements EventListener { PO.clearCrossTenantSafe(); } } - - Session currSess = Executions.getCurrent().getDesktop().getSession(); - HttpSession httpSess = (HttpSession) currSess.getNativeSession(); - int timeout = MSysConfig.getIntValue(MSysConfig.ZK_SESSION_TIMEOUT_IN_SECONDS, -2, - Env.getAD_Client_ID(Env.getCtx()), Env.getAD_Org_ID(Env.getCtx())); - if (timeout != -2) // default to -2 meaning not set - httpSess.setMaxInactiveInterval(timeout); - - String msg = login.validateLogin(m_orgKNPair); - if (!Util.isEmpty(msg)) { - Env.getCtx().clear(); - Dialog.error(0, "Error", msg, new Callback() { - @Override - public void onCallback(Integer result) { - Events.echoEvent(new Event(ON_DEFER_LOGOUT, component)); - } - }); - return; - } - // See if a popup should encourage user to change its password - if (!MUser.get(Env.getCtx()).isNoPasswordReset()) { - int notifyDay = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_PASSWORD_NOTIFY_DAY, 0); - int pwdAgeDay = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_MAX_PASSWORD_AGE_DAY, 0); - if (notifyDay > 0 && pwdAgeDay > 0) { - Timestamp limit = TimeUtil.addDays(MUser.get(Env.getCtx()).getDatePasswordChanged(), pwdAgeDay); - Timestamp notifyAfter = TimeUtil.addDays(limit, -notifyDay); - Timestamp now = TimeUtil.getDay(null); - - if (now.after(notifyAfter)) - Dialog.warn(0, "", Msg.getMsg(m_ctx, "YourPasswordWillExpireInDays", - new Object[] { TimeUtil.getDaysBetween(now, limit) })); - } - } - Env.setContext(m_ctx, "#MFA_Registration_ID", registrationId); - wndLogin.loginCompleted(); + + if (m_isClientDefined) { + wndLogin.showRolePanel(m_userName, m_showRolePanel, m_clientsKNPairs, m_isClientDefined, true); + } else { + if (m_orgKNPair == null) + wndLogin.showRolePanel(m_userName, m_showRolePanel, m_clientsKNPairs, m_isClientDefined, true); + else + wndLogin.loginCompleted(login, m_orgKNPair, this); + } } /** @@ -451,4 +421,8 @@ public class ValidateMFAPanel extends Window implements EventListener { return null; } + public boolean show() { + return m_showMFAPanel; + } + } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java index 477fc8bb90..3c3adf4516 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java @@ -23,26 +23,36 @@ package org.adempiere.webui.window; +import java.sql.Timestamp; import java.util.Locale; import java.util.Properties; +import javax.servlet.http.HttpSession; + +import org.adempiere.util.Callback; import org.adempiere.webui.IWebClient; import org.adempiere.webui.component.FWindow; +import org.adempiere.webui.component.Window; import org.adempiere.webui.panel.ChangePasswordPanel; import org.adempiere.webui.panel.LoginPanel; import org.adempiere.webui.panel.ResetPasswordPanel; import org.adempiere.webui.panel.RolePanel; import org.adempiere.webui.panel.ValidateMFAPanel; import org.adempiere.webui.session.SessionContextListener; +import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ThemeManager; import org.compiere.model.MSysConfig; import org.compiere.model.MUser; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Login; +import org.compiere.util.Msg; +import org.compiere.util.TimeUtil; +import org.compiere.util.Util; import org.zkoss.util.Locales; import org.zkoss.web.Attributes; import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; @@ -62,7 +72,7 @@ public class LoginWindow extends FWindow implements EventListener /** * */ - private static final long serialVersionUID = 2783026164782754864L; + private static final long serialVersionUID = 8570332386555237381L; protected IWebClient app; protected Properties ctx; @@ -72,6 +82,8 @@ public class LoginWindow extends FWindow implements EventListener protected ValidateMFAPanel pnlValidateMFA = null; protected RolePanel pnlRole; + private static final String ON_DEFER_LOGOUT = "onDeferLogout"; + public LoginWindow() {} public void init(IWebClient app) @@ -83,6 +95,7 @@ public class LoginWindow extends FWindow implements EventListener this.setStyle("background-color: transparent"); // add listener on 'ENTER' key for the login window addEventListener(Events.ON_OK,this); + this.addEventListener(ON_DEFER_LOGOUT, this); setWidgetListener("onOK", "zAu.cmd0.showBusy(null)"); } @@ -97,17 +110,31 @@ public class LoginWindow extends FWindow implements EventListener public void loginOk(String userName, boolean show, KeyNamePair[] clientsKNPairs) { - createRolePanel(userName, show, clientsKNPairs); - this.getChildren().clear(); - if (pnlRole.show()) - this.appendChild(pnlRole); - else - this.appendChild(pnlValidateMFA); + boolean isClientDefined = (clientsKNPairs.length == 1); + if (pnlRole == null) + pnlRole = new RolePanel(ctx, this, userName, show, clientsKNPairs, isClientDefined); + if (isClientDefined) { + createValidateMFAPanel(null, isClientDefined, userName, show, clientsKNPairs); + } else { + showRolePanel(userName, show, clientsKNPairs, isClientDefined, false); + if (! pnlRole.show()) + createValidateMFAPanel(null, isClientDefined, userName, show, clientsKNPairs); + } } - protected void createRolePanel(String userName, boolean show, - KeyNamePair[] clientsKNPairs) { - pnlRole = new RolePanel(ctx, this, userName, show, clientsKNPairs); + public void showRolePanel(String userName, boolean show, KeyNamePair[] clientsKNPairs, boolean isClientDefined, boolean isMFAValidated) { + this.getChildren().clear(); + if (pnlRole.show()) { + this.appendChild(pnlRole); + } else if (isMFAValidated) { + pnlRole.validateRoles(isMFAValidated); + } else { + if (!isClientDefined) + if (pnlValidateMFA == null) + createValidateMFAPanel(null, isClientDefined, userName, show, clientsKNPairs); + else + this.appendChild(pnlValidateMFA); + } } public void changePassword(String userName, String userPassword, boolean show, KeyNamePair[] clientsKNPairs) @@ -135,20 +162,55 @@ public class LoginWindow extends FWindow implements EventListener pnlResetPassword = new ResetPasswordPanel(ctx, this, userName, noSecurityQuestion); } - public void validateMFA(KeyNamePair orgKNPair) { + public void validateMFA(KeyNamePair orgKNPair, boolean isClientDefined, String userName, boolean show, KeyNamePair[] clientsKNPairs) { Clients.clearBusy(); - createValidateMFAPanel(orgKNPair); - this.getChildren().clear(); - this.appendChild(pnlValidateMFA); + createValidateMFAPanel(orgKNPair, isClientDefined, userName, show, clientsKNPairs); } - private void createValidateMFAPanel(KeyNamePair orgKNPair) { + private void createValidateMFAPanel(KeyNamePair orgKNPair, boolean isClientDefined, String userName, boolean show, KeyNamePair[] clientsKNPairs) { if (pnlValidateMFA == null) - pnlValidateMFA = new ValidateMFAPanel(ctx, this, orgKNPair); + pnlValidateMFA = new ValidateMFAPanel(ctx, this, orgKNPair, isClientDefined, userName, show, clientsKNPairs); + if (pnlValidateMFA.show()) { + this.getChildren().clear(); + this.appendChild(pnlValidateMFA); + } } - public void loginCompleted() + public void loginCompleted(Login login, KeyNamePair m_orgKNPair, Window component) { + Session currSess = Executions.getCurrent().getDesktop().getSession(); + HttpSession httpSess = (HttpSession) currSess.getNativeSession(); + int timeout = MSysConfig.getIntValue(MSysConfig.ZK_SESSION_TIMEOUT_IN_SECONDS, -2, + Env.getAD_Client_ID(Env.getCtx()), Env.getAD_Org_ID(Env.getCtx())); + if (timeout != -2) // default to -2 meaning not set + httpSess.setMaxInactiveInterval(timeout); + + String msg = login.validateLogin(m_orgKNPair); + if (!Util.isEmpty(msg)) { + Env.getCtx().clear(); + Dialog.error(0, "Error", msg, new Callback() { + @Override + public void onCallback(Integer result) { + Events.echoEvent(new Event(ON_DEFER_LOGOUT, component)); + } + }); + return; + } + // See if a popup should encourage user to change its password + if (!MUser.get(Env.getCtx()).isNoPasswordReset()) { + int notifyDay = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_PASSWORD_NOTIFY_DAY, 0); + int pwdAgeDay = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_MAX_PASSWORD_AGE_DAY, 0); + if (notifyDay > 0 && pwdAgeDay > 0) { + Timestamp limit = TimeUtil.addDays(MUser.get(Env.getCtx()).getDatePasswordChanged(), pwdAgeDay); + Timestamp notifyAfter = TimeUtil.addDays(limit, -notifyDay); + Timestamp now = TimeUtil.getDay(null); + + if (now.after(notifyAfter)) + Dialog.warn(0, "", Msg.getMsg(Env.getCtx(), "YourPasswordWillExpireInDays", + new Object[] { TimeUtil.getDaysBetween(now, limit) })); + } + } + app.loginCompleted(); } @@ -173,7 +235,7 @@ public class LoginWindow extends FWindow implements EventListener RolePanel rolePanel = (RolePanel)this.getFellowIfAny("rolePanel"); if (rolePanel != null) { - rolePanel.validateRoles(); + rolePanel.validateRoles(false); return; } @@ -201,6 +263,8 @@ public class LoginWindow extends FWindow implements EventListener validateMFAPanel.validateMFAComplete(true); return; } + } else if (ON_DEFER_LOGOUT.equals(event.getName())) { + SessionManager.logoutSession(); } }