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 <hengsin@gmail.com>
This commit is contained in:
Carlos Ruiz 2022-10-04 11:14:05 +02:00 committed by GitHub
parent 96a46e5bac
commit c1a1045d87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 574 additions and 127 deletions

View File

@ -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')
;

View File

@ -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')
;

View File

@ -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

View File

@ -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();
@ -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";

View File

@ -57,7 +57,7 @@ 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

View File

@ -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())
{

View File

@ -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";

View File

@ -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

View File

@ -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)
@ -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 */

View File

@ -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<MUser> 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())

View File

@ -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<Event>
MPasswordRule pwdrule = MPasswordRule.getRules(Env.getCtx(), null);
if (pwdrule != null) {
try {
pwdrule.validate(m_userName, txtNewPassword.getValue(), new ArrayList<MPasswordHistory>());
pwdrule.validate(Login.getAppUser(m_userName), txtNewPassword.getValue(), new ArrayList<MPasswordHistory>());
}
catch (Exception e) {
throw new WrongValueException(txtNewPassword, e.getMessage());
@ -346,7 +347,7 @@ public class ChangePasswordPanel extends Window implements EventListener<Event>
{
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();

View File

@ -102,7 +102,7 @@ public class LoginPanel extends Window implements EventListener<Event>
/**
*
*/
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<Event>
{
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<Event>
}
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<Event>
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());

View File

@ -80,7 +80,7 @@ public class RolePanel extends Window implements EventListener<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, Deferrabl
auf = new AuFocus(lstOrganisation);
}
Clients.response(auf);
} else {
validateRoles();
}
}
@ -348,7 +349,7 @@ public class RolePanel extends Window implements EventListener<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, Deferrabl
}
public boolean show() {
return m_show;
return m_showRolePanel;
}
}

View File

@ -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<Event> {
/**
*
*/
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<Event> {
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<Event> {
/* 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<Event> {
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<Event> {
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<Event> {
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<Integer>() {
@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<Event> {
return null;
}
public boolean show() {
return m_showMFAPanel;
}
}

View File

@ -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<Event>
/**
*
*/
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<Event>
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<Event>
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<Event>
public void loginOk(String userName, boolean show, KeyNamePair[] clientsKNPairs)
{
createRolePanel(userName, show, clientsKNPairs);
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);
}
}
public void showRolePanel(String userName, boolean show, KeyNamePair[] clientsKNPairs, boolean isClientDefined, boolean isMFAValidated) {
this.getChildren().clear();
if (pnlRole.show())
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);
}
protected void createRolePanel(String userName, boolean show,
KeyNamePair[] clientsKNPairs) {
pnlRole = new RolePanel(ctx, this, userName, show, clientsKNPairs);
}
public void changePassword(String userName, String userPassword, boolean show, KeyNamePair[] clientsKNPairs)
@ -135,20 +162,55 @@ public class LoginWindow extends FWindow implements EventListener<Event>
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);
createValidateMFAPanel(orgKNPair, isClientDefined, userName, show, clientsKNPairs);
}
private void createValidateMFAPanel(KeyNamePair orgKNPair, boolean isClientDefined, String userName, boolean show, KeyNamePair[] clientsKNPairs) {
if (pnlValidateMFA == null)
pnlValidateMFA = new ValidateMFAPanel(ctx, this, orgKNPair, isClientDefined, userName, show, clientsKNPairs);
if (pnlValidateMFA.show()) {
this.getChildren().clear();
this.appendChild(pnlValidateMFA);
}
private void createValidateMFAPanel(KeyNamePair orgKNPair) {
if (pnlValidateMFA == null)
pnlValidateMFA = new ValidateMFAPanel(ctx, this, orgKNPair);
}
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<Integer>() {
@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<Event>
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<Event>
validateMFAPanel.validateMFAComplete(true);
return;
}
} else if (ON_DEFER_LOGOUT.equals(event.getName())) {
SessionManager.logoutSession();
}
}