IDEMPIERE-4782 Multi-factor authentication (FHCA-2034) (#705)
* IDEMPIERE-4782 Multi-factor authentication (FHCA-2034) Implement suggestions from Heng Sin * IDEMPIERE-4782 Multi-factor authentication (FHCA-2034) Fix security warning advised by github/CodeQL * IDEMPIERE-4782 Multi-factor authentication (FHCA-2034) Implement an incremental delay in zk when the validation code is wrong (to avoid brute-force attacks) As suggested by Ricardo Santana: * ensures one-time only use of an OTP * Log failures in AuthFailure.log * IDEMPIERE-4782 Multi-factor authentication (FHCA-2034) * Log failures in AuthFailure.log - add case for login with email * Implement incremental delay also for login panel
This commit is contained in:
parent
3e64dc6737
commit
a4f67eb852
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,95 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-4782 Multi-factor authentication (FHCA-2034)
|
||||
-- Jun 7, 2021, 9:39:32 PM CEST
|
||||
INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203515,0,0,'Y',TO_DATE('2021-06-07 21:39:32','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:39:32','YYYY-MM-DD HH24:MI:SS'),100,'MFALastSecret','Last MFA Secret','Last MFA Secret','D','e65db29f-25a3-4b07-acd3-1d442897e22f')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:02:33 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) VALUES (214500,0,'Last MFA Secret',200275,'MFALastSecret',2000,'N','N','N','N','N',0,'N',10,0,0,'Y',TO_DATE('2021-06-07 21:02:32','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:02:32','YYYY-MM-DD HH24:MI:SS'),100,203515,'Y','N','D','N','N','N','Y','13927461-61b7-4008-b867-25147cbc6eb3','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:02:59 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 (203513,0,0,'Y',TO_DATE('2021-06-07 21:02:48','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:02:48','YYYY-MM-DD HH24:MI:SS'),100,'LastSuccess','Last Success',NULL,NULL,'Last Success','D','b9882967-1536-463b-ba6b-e185ea647e20')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:03:07 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) VALUES (214501,0,'Last Success',200275,'LastSuccess',7,'N','N','N','N','N',0,'N',16,0,0,'Y',TO_DATE('2021-06-07 21:03:07','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:03:07','YYYY-MM-DD HH24:MI:SS'),100,203513,'Y','N','D','N','N','N','Y','b71e7f11-90be-4596-8368-26fd0a0606af','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:03:32 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD MFALastSecret VARCHAR2(2000 CHAR) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:03:56 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD LastSuccess DATE DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:16 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 (203514,0,0,'Y',TO_DATE('2021-06-07 21:04:09','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:04:09','YYYY-MM-DD HH24:MI:SS'),100,'LastFailure','Last Failure',NULL,NULL,'Last Failure','D','d1f7a3ad-db3c-47a1-9d6a-67163d72a88d')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:20 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) VALUES (214502,0,'Last Failure',200275,'LastFailure',7,'N','N','N','N','N',0,'N',16,0,0,'Y',TO_DATE('2021-06-07 21:04:20','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:04:20','YYYY-MM-DD HH24:MI:SS'),100,203514,'Y','N','D','N','N','N','Y','3dff6b96-912a-405e-bcf4-662466d708f6','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:21 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD LastFailure DATE DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:56 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) VALUES (214503,0,'Failed Login Count',200275,'FailedLoginCount',10,'N','N','N','N','N',0,'N',11,0,0,'Y',TO_DATE('2021-06-07 21:04:56','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:04:56','YYYY-MM-DD HH24:MI:SS'),100,200113,'N','N','D','N','N','N','Y','ab6cf862-137c-4b10-939a-f97b19dc3943','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:58 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD FailedLoginCount NUMBER(10) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:11 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 (206666,'Last MFA Secret',200290,214500,'Y',2000,160,'N','N','N','N',0,0,'Y',TO_DATE('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','f1754863-8ed2-468c-be3a-6ebff14996a7','Y',150,5)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:12 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 (206667,'Last Success',200290,214501,'Y',7,170,'N','N','N','N',0,0,'Y',TO_DATE('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','b2473190-ee58-47fb-b99a-d21242187b7f','Y',160,2)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:12 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 (206668,'Last Failure',200290,214502,'Y',7,180,'N','N','N','N',0,0,'Y',TO_DATE('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','57cce993-f54c-48c0-b130-384162ab73ea','Y',170,2)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:12 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 (206669,'Failed Login Count',200290,214503,'Y',10,190,'N','N','N','N',0,0,'Y',TO_DATE('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','d5738f08-cdfe-4417-97c1-875db62bf899','Y',180,2)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=130, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206651
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=140, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206652
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=150, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, ColumnSpan=2, IsToolbarButton=NULL,Updated=TO_DATE('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206666
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=160, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=4, IsToolbarButton=NULL,Updated=TO_DATE('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206667
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=170, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206668
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=180, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=4, IsToolbarButton=NULL,Updated=TO_DATE('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206669
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:58:42 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','The one-time validation code has been used, please try again with a different code',0,0,'Y',TO_DATE('2021-06-07 21:58:41','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-06-07 21:58:41','YYYY-MM-DD HH24:MI:SS'),100,200710,'MFACodeAlreadyConsumed','D','a1c11929-d6ae-410b-a57a-eb9f6259fbee')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('202106072201_IDEMPIERE-4782.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
-- IDEMPIERE-4782 Multi-factor authentication (FHCA-2034)
|
||||
-- Jun 7, 2021, 9:39:32 PM CEST
|
||||
INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,PrintName,EntityType,AD_Element_UU) VALUES (203515,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:39:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:39:32','YYYY-MM-DD HH24:MI:SS'),100,'MFALastSecret','Last MFA Secret','Last MFA Secret','D','e65db29f-25a3-4b07-acd3-1d442897e22f')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:02:33 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) VALUES (214500,0,'Last MFA Secret',200275,'MFALastSecret',2000,'N','N','N','N','N',0,'N',10,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:02:32','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:02:32','YYYY-MM-DD HH24:MI:SS'),100,203515,'Y','N','D','N','N','N','Y','13927461-61b7-4008-b867-25147cbc6eb3','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:02:59 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 (203513,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:02:48','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:02:48','YYYY-MM-DD HH24:MI:SS'),100,'LastSuccess','Last Success',NULL,NULL,'Last Success','D','b9882967-1536-463b-ba6b-e185ea647e20')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:03:07 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) VALUES (214501,0,'Last Success',200275,'LastSuccess',7,'N','N','N','N','N',0,'N',16,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:03:07','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:03:07','YYYY-MM-DD HH24:MI:SS'),100,203513,'Y','N','D','N','N','N','Y','b71e7f11-90be-4596-8368-26fd0a0606af','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:03:32 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD COLUMN MFALastSecret VARCHAR(2000) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:03:56 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD COLUMN LastSuccess TIMESTAMP DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:16 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 (203514,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:04:09','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:04:09','YYYY-MM-DD HH24:MI:SS'),100,'LastFailure','Last Failure',NULL,NULL,'Last Failure','D','d1f7a3ad-db3c-47a1-9d6a-67163d72a88d')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:20 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) VALUES (214502,0,'Last Failure',200275,'LastFailure',7,'N','N','N','N','N',0,'N',16,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:04:20','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:04:20','YYYY-MM-DD HH24:MI:SS'),100,203514,'Y','N','D','N','N','N','Y','3dff6b96-912a-405e-bcf4-662466d708f6','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:21 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD COLUMN LastFailure TIMESTAMP DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:56 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) VALUES (214503,0,'Failed Login Count',200275,'FailedLoginCount',10,'N','N','N','N','N',0,'N',11,0,0,'Y',TO_TIMESTAMP('2021-06-07 21:04:56','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:04:56','YYYY-MM-DD HH24:MI:SS'),100,200113,'N','N','D','N','N','N','Y','ab6cf862-137c-4b10-939a-f97b19dc3943','Y',0,'N','N','N','N')
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:04:58 PM CEST
|
||||
ALTER TABLE MFA_Registration ADD COLUMN FailedLoginCount NUMERIC(10) DEFAULT NULL
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:11 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 (206666,'Last MFA Secret',200290,214500,'Y',2000,160,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','f1754863-8ed2-468c-be3a-6ebff14996a7','Y',150,5)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:12 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 (206667,'Last Success',200290,214501,'Y',7,170,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:05:11','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','b2473190-ee58-47fb-b99a-d21242187b7f','Y',160,2)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:12 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 (206668,'Last Failure',200290,214502,'Y',7,180,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','57cce993-f54c-48c0-b130-384162ab73ea','Y',170,2)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:12 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 (206669,'Failed Login Count',200290,214503,'Y',10,190,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:05:12','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','d5738f08-cdfe-4417-97c1-875db62bf899','Y',180,2)
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=130, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206651
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=140, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206652
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=150, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, ColumnSpan=2, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206666
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=160, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=4, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206667
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET SeqNo=170, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206668
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:05:50 PM CEST
|
||||
UPDATE AD_Field SET IsDisplayed='Y', SeqNo=180, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, XPosition=4, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2021-06-07 21:05:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=206669
|
||||
;
|
||||
|
||||
-- Jun 7, 2021, 9:58:42 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','The one-time validation code has been used, please try again with a different code',0,0,'Y',TO_TIMESTAMP('2021-06-07 21:58:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-06-07 21:58:41','YYYY-MM-DD HH24:MI:SS'),100,200710,'MFACodeAlreadyConsumed','D','a1c11929-d6ae-410b-a57a-eb9f6259fbee')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('202106072201_IDEMPIERE-4782.sql') FROM dual
|
||||
;
|
||||
|
|
@ -90,6 +90,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -107,6 +107,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -104,6 +104,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -105,6 +105,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -104,6 +104,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ds.core.builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
|
|
|
@ -151,6 +151,8 @@ Require-Bundle: org.eclipse.equinox.app;bundle-version="0.0.0",
|
|||
wrapped.com.google.http-client.google-http-client-gson;bundle-version="1.38.1",
|
||||
org.apache.httpcomponents.httpclient;bundle-version="4.5.10",
|
||||
org.apache.httpcomponents.httpcore;bundle-version="4.4.12",
|
||||
com.google.guava;bundle-version="28.2.0"
|
||||
com.google.guava;bundle-version="28.2.0",
|
||||
wrapped.com.google.zxing.javase;bundle-version="3.4.1",
|
||||
wrapped.dev.samstevens.totp.totp;bundle-version="1.7.1"
|
||||
Automatic-Module-Name: org.adempiere.base
|
||||
Bundle-Vendor: iDempiere Community
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.idempiere.mfa.EMailMechanism">
|
||||
<implementation class="org.idempiere.mfa.EMailMechanism"/>
|
||||
<service>
|
||||
<provide interface="org.compiere.model.IMFAMechanism"/>
|
||||
</service>
|
||||
<property name="method" type="String" value="EMail"/>
|
||||
</scr:component>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.idempiere.mfa.TOTPMechanism">
|
||||
<implementation class="org.idempiere.mfa.TOTPMechanism"/>
|
||||
<service>
|
||||
<provide interface="org.compiere.model.IMFAMechanism"/>
|
||||
</service>
|
||||
<property name="method" type="String" value="TOTP"/>
|
||||
</scr:component>
|
|
@ -1,20 +1,5 @@
|
|||
bin.includes = plugin.xml,\
|
||||
OSGI-INF/,\
|
||||
OSGI-INF/dslocator.xml,\
|
||||
OSGI-INF/defaultmodelfactory.xml,\
|
||||
OSGI-INF/defaultdocfactory.xml,\
|
||||
OSGI-INF/defaultcolumncalloutfactory.xml,\
|
||||
OSGI-INF/defaultmodelvalidatorfactory.xml,\
|
||||
OSGI-INF/defaultprocessfactory.xml,\
|
||||
OSGI-INF/defaultshipmentprocessorfactory.xml,\
|
||||
OSGI-INF/defaultpaymentprocessorfactory.xml,\
|
||||
OSGI-INF/broadcastutil.xml,\
|
||||
OSGI-INF/requesteventhandler.xml,\
|
||||
OSGI-INF/requestpropertyservice.xml,\
|
||||
OSGI-INF/defaultaddressvalidationfactory.xml,\
|
||||
OSGI-INF/defaulttaxproviderfactory.xml,\
|
||||
OSGI-INF/addressvalidationeventhandler.xml,\
|
||||
OSGI-INF/defaultproductpricingfactory.xml,\
|
||||
schema/,\
|
||||
.,\
|
||||
META-INF/,\
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.model;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public interface IMFAMechanism {
|
||||
|
||||
/**
|
||||
* Registration mechanism for the method
|
||||
* Here the registration method executes the actions expected for this method, like sending an email, or an SMS, or nothing
|
||||
* and creates the registration record
|
||||
* @param ctx
|
||||
* @param method
|
||||
* @param prm optional, for example the email
|
||||
* @param trxName
|
||||
* @return Object[] - first object is the String with the instructions to follow
|
||||
* second object is the registration generated
|
||||
* third and posterior objects are optional additional information for the method
|
||||
* like QRCode image for example, or html img object, or URL, or File
|
||||
*/
|
||||
Object[] register(Properties ctx, MMFAMethod method, String prm, String trxName);
|
||||
|
||||
/**
|
||||
* Complete/Validate a previous registration
|
||||
* Here it must check for validity of the mechanism, mark the record as valid or throw exception when not
|
||||
* @param ctx
|
||||
* @param reg The registration object
|
||||
* @param code The code to be validated
|
||||
* @param name Optional - a name to assign the registration
|
||||
* @param preferred
|
||||
* @param trxName
|
||||
* @return msg A message indicating success, errors throw exception
|
||||
*/
|
||||
String complete(Properties ctx, MMFARegistration reg, String code, String name, boolean preferred, String trxName);
|
||||
|
||||
/**
|
||||
* Generate a validation code (when needed depending on the method)
|
||||
* @param reg
|
||||
* @return
|
||||
*/
|
||||
String generateValidationCode(MMFARegistration reg);
|
||||
|
||||
/**
|
||||
* Validate a code
|
||||
* @param reg
|
||||
* @param code
|
||||
* @param setPreferred
|
||||
* @return message on error, null when OK
|
||||
*/
|
||||
String validateCode(MMFARegistration reg, String code, boolean setPreferred);
|
||||
|
||||
}
|
|
@ -0,0 +1,263 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
||||
/** Generated Interface for MFA_Method
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2
|
||||
*/
|
||||
public interface I_MFA_Method
|
||||
{
|
||||
|
||||
/** TableName=MFA_Method */
|
||||
public static final String Table_Name = "MFA_Method";
|
||||
|
||||
/** AD_Table_ID=200273 */
|
||||
public static final int Table_ID = 200273;
|
||||
|
||||
KeyNamePair Model = new KeyNamePair(Table_ID, Table_Name);
|
||||
|
||||
/** AccessLevel = 4 - System
|
||||
*/
|
||||
BigDecimal accessLevel = BigDecimal.valueOf(4);
|
||||
|
||||
/** Load Meta Data */
|
||||
|
||||
/** Column name AD_Client_ID */
|
||||
public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID";
|
||||
|
||||
/** Get Client.
|
||||
* Client/Tenant for this installation.
|
||||
*/
|
||||
public int getAD_Client_ID();
|
||||
|
||||
/** Column name AD_Org_ID */
|
||||
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";
|
||||
|
||||
/** Set Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public void setAD_Org_ID (int AD_Org_ID);
|
||||
|
||||
/** Get Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public int getAD_Org_ID();
|
||||
|
||||
/** Column name Created */
|
||||
public static final String COLUMNNAME_Created = "Created";
|
||||
|
||||
/** Get Created.
|
||||
* Date this record was created
|
||||
*/
|
||||
public Timestamp getCreated();
|
||||
|
||||
/** Column name CreatedBy */
|
||||
public static final String COLUMNNAME_CreatedBy = "CreatedBy";
|
||||
|
||||
/** Get Created By.
|
||||
* User who created this records
|
||||
*/
|
||||
public int getCreatedBy();
|
||||
|
||||
/** Column name Description */
|
||||
public static final String COLUMNNAME_Description = "Description";
|
||||
|
||||
/** Set Description.
|
||||
* Optional short description of the record
|
||||
*/
|
||||
public void setDescription (String Description);
|
||||
|
||||
/** Get Description.
|
||||
* Optional short description of the record
|
||||
*/
|
||||
public String getDescription();
|
||||
|
||||
/** Column name ExpireInMinutes */
|
||||
public static final String COLUMNNAME_ExpireInMinutes = "ExpireInMinutes";
|
||||
|
||||
/** Set Expire in Minutes */
|
||||
public void setExpireInMinutes (int ExpireInMinutes);
|
||||
|
||||
/** Get Expire in Minutes */
|
||||
public int getExpireInMinutes();
|
||||
|
||||
/** Column name Help */
|
||||
public static final String COLUMNNAME_Help = "Help";
|
||||
|
||||
/** Set Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help);
|
||||
|
||||
/** Get Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public String getHelp();
|
||||
|
||||
/** Column name IsActive */
|
||||
public static final String COLUMNNAME_IsActive = "IsActive";
|
||||
|
||||
/** Set Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public void setIsActive (boolean IsActive);
|
||||
|
||||
/** Get Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public boolean isActive();
|
||||
|
||||
/** Column name Method */
|
||||
public static final String COLUMNNAME_Method = "Method";
|
||||
|
||||
/** Set Method */
|
||||
public void setMethod (String Method);
|
||||
|
||||
/** Get Method */
|
||||
public String getMethod();
|
||||
|
||||
/** Column name MFAAllowedTimeDiscrepancy */
|
||||
public static final String COLUMNNAME_MFAAllowedTimeDiscrepancy = "MFAAllowedTimeDiscrepancy";
|
||||
|
||||
/** Set Allowed Time Period Discrepancy */
|
||||
public void setMFAAllowedTimeDiscrepancy (int MFAAllowedTimeDiscrepancy);
|
||||
|
||||
/** Get Allowed Time Period Discrepancy */
|
||||
public int getMFAAllowedTimeDiscrepancy();
|
||||
|
||||
/** Column name MFA_ElementPrm_ID */
|
||||
public static final String COLUMNNAME_MFA_ElementPrm_ID = "MFA_ElementPrm_ID";
|
||||
|
||||
/** Set Parameter Element */
|
||||
public void setMFA_ElementPrm_ID (int MFA_ElementPrm_ID);
|
||||
|
||||
/** Get Parameter Element */
|
||||
public int getMFA_ElementPrm_ID();
|
||||
|
||||
public org.compiere.model.I_AD_Element getMFA_ElementPrm() throws RuntimeException;
|
||||
|
||||
/** Column name MFAIssuer */
|
||||
public static final String COLUMNNAME_MFAIssuer = "MFAIssuer";
|
||||
|
||||
/** Set Issuer */
|
||||
public void setMFAIssuer (String MFAIssuer);
|
||||
|
||||
/** Get Issuer */
|
||||
public String getMFAIssuer();
|
||||
|
||||
/** Column name MFA_Method_ID */
|
||||
public static final String COLUMNNAME_MFA_Method_ID = "MFA_Method_ID";
|
||||
|
||||
/** Set MFA Method.
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public void setMFA_Method_ID (int MFA_Method_ID);
|
||||
|
||||
/** Get MFA Method.
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public int getMFA_Method_ID();
|
||||
|
||||
/** Column name MFA_Method_UU */
|
||||
public static final String COLUMNNAME_MFA_Method_UU = "MFA_Method_UU";
|
||||
|
||||
/** Set MFA_Method_UU */
|
||||
public void setMFA_Method_UU (String MFA_Method_UU);
|
||||
|
||||
/** Get MFA_Method_UU */
|
||||
public String getMFA_Method_UU();
|
||||
|
||||
/** Column name MFATimeProvider */
|
||||
public static final String COLUMNNAME_MFATimeProvider = "MFATimeProvider";
|
||||
|
||||
/** Set Time Provider */
|
||||
public void setMFATimeProvider (String MFATimeProvider);
|
||||
|
||||
/** Get Time Provider */
|
||||
public String getMFATimeProvider();
|
||||
|
||||
/** Column name MFATimeServer */
|
||||
public static final String COLUMNNAME_MFATimeServer = "MFATimeServer";
|
||||
|
||||
/** Set Time Server */
|
||||
public void setMFATimeServer (String MFATimeServer);
|
||||
|
||||
/** Get Time Server */
|
||||
public String getMFATimeServer();
|
||||
|
||||
/** Column name MFAType */
|
||||
public static final String COLUMNNAME_MFAType = "MFAType";
|
||||
|
||||
/** Set MFA Type.
|
||||
* Multi-factor authentication type (Something you Know/Have/Are, Location)
|
||||
*/
|
||||
public void setMFAType (String MFAType);
|
||||
|
||||
/** Get MFA Type.
|
||||
* Multi-factor authentication type (Something you Know/Have/Are, Location)
|
||||
*/
|
||||
public String getMFAType();
|
||||
|
||||
/** Column name Name */
|
||||
public static final String COLUMNNAME_Name = "Name";
|
||||
|
||||
/** Set Name.
|
||||
* Alphanumeric identifier of the entity
|
||||
*/
|
||||
public void setName (String Name);
|
||||
|
||||
/** Get Name.
|
||||
* Alphanumeric identifier of the entity
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/** Column name R_MailText_ID */
|
||||
public static final String COLUMNNAME_R_MailText_ID = "R_MailText_ID";
|
||||
|
||||
/** Set Mail Template.
|
||||
* Text templates for mailings
|
||||
*/
|
||||
public void setR_MailText_ID (int R_MailText_ID);
|
||||
|
||||
/** Get Mail Template.
|
||||
* Text templates for mailings
|
||||
*/
|
||||
public int getR_MailText_ID();
|
||||
|
||||
public org.compiere.model.I_R_MailText getR_MailText() throws RuntimeException;
|
||||
|
||||
/** Column name Updated */
|
||||
public static final String COLUMNNAME_Updated = "Updated";
|
||||
|
||||
/** Get Updated.
|
||||
* Date this record was updated
|
||||
*/
|
||||
public Timestamp getUpdated();
|
||||
|
||||
/** Column name UpdatedBy */
|
||||
public static final String COLUMNNAME_UpdatedBy = "UpdatedBy";
|
||||
|
||||
/** Get Updated By.
|
||||
* User who updated this records
|
||||
*/
|
||||
public int getUpdatedBy();
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
||||
/** Generated Interface for MFA_RegisteredDevice
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2
|
||||
*/
|
||||
public interface I_MFA_RegisteredDevice
|
||||
{
|
||||
|
||||
/** TableName=MFA_RegisteredDevice */
|
||||
public static final String Table_Name = "MFA_RegisteredDevice";
|
||||
|
||||
/** AD_Table_ID=200274 */
|
||||
public static final int Table_ID = 200274;
|
||||
|
||||
KeyNamePair Model = new KeyNamePair(Table_ID, Table_Name);
|
||||
|
||||
/** AccessLevel = 6 - System - Client
|
||||
*/
|
||||
BigDecimal accessLevel = BigDecimal.valueOf(6);
|
||||
|
||||
/** Load Meta Data */
|
||||
|
||||
/** Column name AD_Client_ID */
|
||||
public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID";
|
||||
|
||||
/** Get Client.
|
||||
* Client/Tenant for this installation.
|
||||
*/
|
||||
public int getAD_Client_ID();
|
||||
|
||||
/** Column name AD_Org_ID */
|
||||
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";
|
||||
|
||||
/** Set Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public void setAD_Org_ID (int AD_Org_ID);
|
||||
|
||||
/** Get Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public int getAD_Org_ID();
|
||||
|
||||
/** Column name AD_User_ID */
|
||||
public static final String COLUMNNAME_AD_User_ID = "AD_User_ID";
|
||||
|
||||
/** Set User/Contact.
|
||||
* User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public void setAD_User_ID (int AD_User_ID);
|
||||
|
||||
/** Get User/Contact.
|
||||
* User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public int getAD_User_ID();
|
||||
|
||||
public org.compiere.model.I_AD_User getAD_User() throws RuntimeException;
|
||||
|
||||
/** Column name Created */
|
||||
public static final String COLUMNNAME_Created = "Created";
|
||||
|
||||
/** Get Created.
|
||||
* Date this record was created
|
||||
*/
|
||||
public Timestamp getCreated();
|
||||
|
||||
/** Column name CreatedBy */
|
||||
public static final String COLUMNNAME_CreatedBy = "CreatedBy";
|
||||
|
||||
/** Get Created By.
|
||||
* User who created this records
|
||||
*/
|
||||
public int getCreatedBy();
|
||||
|
||||
/** Column name Expiration */
|
||||
public static final String COLUMNNAME_Expiration = "Expiration";
|
||||
|
||||
/** Set Expire On.
|
||||
* Expire On
|
||||
*/
|
||||
public void setExpiration (Timestamp Expiration);
|
||||
|
||||
/** Get Expire On.
|
||||
* Expire On
|
||||
*/
|
||||
public Timestamp getExpiration();
|
||||
|
||||
/** Column name Help */
|
||||
public static final String COLUMNNAME_Help = "Help";
|
||||
|
||||
/** Set Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help);
|
||||
|
||||
/** Get Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public String getHelp();
|
||||
|
||||
/** Column name IsActive */
|
||||
public static final String COLUMNNAME_IsActive = "IsActive";
|
||||
|
||||
/** Set Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public void setIsActive (boolean IsActive);
|
||||
|
||||
/** Get Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public boolean isActive();
|
||||
|
||||
/** Column name MFADeviceIdentifier */
|
||||
public static final String COLUMNNAME_MFADeviceIdentifier = "MFADeviceIdentifier";
|
||||
|
||||
/** Set MFA Device Identifier.
|
||||
* Multi-factor Authentication Device Identifier
|
||||
*/
|
||||
public void setMFADeviceIdentifier (String MFADeviceIdentifier);
|
||||
|
||||
/** Get MFA Device Identifier.
|
||||
* Multi-factor Authentication Device Identifier
|
||||
*/
|
||||
public String getMFADeviceIdentifier();
|
||||
|
||||
/** Column name MFA_RegisteredDevice_ID */
|
||||
public static final String COLUMNNAME_MFA_RegisteredDevice_ID = "MFA_RegisteredDevice_ID";
|
||||
|
||||
/** Set MFA Registered Device */
|
||||
public void setMFA_RegisteredDevice_ID (int MFA_RegisteredDevice_ID);
|
||||
|
||||
/** Get MFA Registered Device */
|
||||
public int getMFA_RegisteredDevice_ID();
|
||||
|
||||
/** Column name MFA_RegisteredDevice_UU */
|
||||
public static final String COLUMNNAME_MFA_RegisteredDevice_UU = "MFA_RegisteredDevice_UU";
|
||||
|
||||
/** Set MFA_RegisteredDevice_UU */
|
||||
public void setMFA_RegisteredDevice_UU (String MFA_RegisteredDevice_UU);
|
||||
|
||||
/** Get MFA_RegisteredDevice_UU */
|
||||
public String getMFA_RegisteredDevice_UU();
|
||||
|
||||
/** Column name Updated */
|
||||
public static final String COLUMNNAME_Updated = "Updated";
|
||||
|
||||
/** Get Updated.
|
||||
* Date this record was updated
|
||||
*/
|
||||
public Timestamp getUpdated();
|
||||
|
||||
/** Column name UpdatedBy */
|
||||
public static final String COLUMNNAME_UpdatedBy = "UpdatedBy";
|
||||
|
||||
/** Get Updated By.
|
||||
* User who updated this records
|
||||
*/
|
||||
public int getUpdatedBy();
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
||||
/** Generated Interface for MFA_Registration
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2
|
||||
*/
|
||||
public interface I_MFA_Registration
|
||||
{
|
||||
|
||||
/** TableName=MFA_Registration */
|
||||
public static final String Table_Name = "MFA_Registration";
|
||||
|
||||
/** AD_Table_ID=200275 */
|
||||
public static final int Table_ID = 200275;
|
||||
|
||||
KeyNamePair Model = new KeyNamePair(Table_ID, Table_Name);
|
||||
|
||||
/** AccessLevel = 6 - System - Client
|
||||
*/
|
||||
BigDecimal accessLevel = BigDecimal.valueOf(6);
|
||||
|
||||
/** Load Meta Data */
|
||||
|
||||
/** Column name AD_Client_ID */
|
||||
public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID";
|
||||
|
||||
/** Get Client.
|
||||
* Client/Tenant for this installation.
|
||||
*/
|
||||
public int getAD_Client_ID();
|
||||
|
||||
/** Column name AD_Org_ID */
|
||||
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";
|
||||
|
||||
/** Set Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public void setAD_Org_ID (int AD_Org_ID);
|
||||
|
||||
/** Get Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public int getAD_Org_ID();
|
||||
|
||||
/** Column name AD_User_ID */
|
||||
public static final String COLUMNNAME_AD_User_ID = "AD_User_ID";
|
||||
|
||||
/** Set User/Contact.
|
||||
* User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public void setAD_User_ID (int AD_User_ID);
|
||||
|
||||
/** Get User/Contact.
|
||||
* User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public int getAD_User_ID();
|
||||
|
||||
public org.compiere.model.I_AD_User getAD_User() throws RuntimeException;
|
||||
|
||||
/** Column name Created */
|
||||
public static final String COLUMNNAME_Created = "Created";
|
||||
|
||||
/** Get Created.
|
||||
* Date this record was created
|
||||
*/
|
||||
public Timestamp getCreated();
|
||||
|
||||
/** Column name CreatedBy */
|
||||
public static final String COLUMNNAME_CreatedBy = "CreatedBy";
|
||||
|
||||
/** Get Created By.
|
||||
* User who created this records
|
||||
*/
|
||||
public int getCreatedBy();
|
||||
|
||||
/** Column name Expiration */
|
||||
public static final String COLUMNNAME_Expiration = "Expiration";
|
||||
|
||||
/** Set Expire On.
|
||||
* Expire On
|
||||
*/
|
||||
public void setExpiration (Timestamp Expiration);
|
||||
|
||||
/** Get Expire On.
|
||||
* Expire On
|
||||
*/
|
||||
public Timestamp getExpiration();
|
||||
|
||||
/** Column name FailedLoginCount */
|
||||
public static final String COLUMNNAME_FailedLoginCount = "FailedLoginCount";
|
||||
|
||||
/** Set Failed Login Count */
|
||||
public void setFailedLoginCount (int FailedLoginCount);
|
||||
|
||||
/** Get Failed Login Count */
|
||||
public int getFailedLoginCount();
|
||||
|
||||
/** Column name Help */
|
||||
public static final String COLUMNNAME_Help = "Help";
|
||||
|
||||
/** Set Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help);
|
||||
|
||||
/** Get Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public String getHelp();
|
||||
|
||||
/** Column name IsActive */
|
||||
public static final String COLUMNNAME_IsActive = "IsActive";
|
||||
|
||||
/** Set Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public void setIsActive (boolean IsActive);
|
||||
|
||||
/** Get Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public boolean isActive();
|
||||
|
||||
/** Column name IsUserMFAPreferred */
|
||||
public static final String COLUMNNAME_IsUserMFAPreferred = "IsUserMFAPreferred";
|
||||
|
||||
/** Set Preferred */
|
||||
public void setIsUserMFAPreferred (boolean IsUserMFAPreferred);
|
||||
|
||||
/** Get Preferred */
|
||||
public boolean isUserMFAPreferred();
|
||||
|
||||
/** Column name IsValid */
|
||||
public static final String COLUMNNAME_IsValid = "IsValid";
|
||||
|
||||
/** Set Valid.
|
||||
* Element is valid
|
||||
*/
|
||||
public void setIsValid (boolean IsValid);
|
||||
|
||||
/** Get Valid.
|
||||
* Element is valid
|
||||
*/
|
||||
public boolean isValid();
|
||||
|
||||
/** Column name LastFailure */
|
||||
public static final String COLUMNNAME_LastFailure = "LastFailure";
|
||||
|
||||
/** Set Last Failure */
|
||||
public void setLastFailure (Timestamp LastFailure);
|
||||
|
||||
/** Get Last Failure */
|
||||
public Timestamp getLastFailure();
|
||||
|
||||
/** Column name LastSuccess */
|
||||
public static final String COLUMNNAME_LastSuccess = "LastSuccess";
|
||||
|
||||
/** Set Last Success */
|
||||
public void setLastSuccess (Timestamp LastSuccess);
|
||||
|
||||
/** Get Last Success */
|
||||
public Timestamp getLastSuccess();
|
||||
|
||||
/** Column name MFALastSecret */
|
||||
public static final String COLUMNNAME_MFALastSecret = "MFALastSecret";
|
||||
|
||||
/** Set Last MFA Secret */
|
||||
public void setMFALastSecret (String MFALastSecret);
|
||||
|
||||
/** Get Last MFA Secret */
|
||||
public String getMFALastSecret();
|
||||
|
||||
/** Column name MFA_Method_ID */
|
||||
public static final String COLUMNNAME_MFA_Method_ID = "MFA_Method_ID";
|
||||
|
||||
/** Set MFA Method.
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public void setMFA_Method_ID (int MFA_Method_ID);
|
||||
|
||||
/** Get MFA Method.
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public int getMFA_Method_ID();
|
||||
|
||||
public org.compiere.model.I_MFA_Method getMFA_Method() throws RuntimeException;
|
||||
|
||||
/** Column name MFA_Registration_ID */
|
||||
public static final String COLUMNNAME_MFA_Registration_ID = "MFA_Registration_ID";
|
||||
|
||||
/** Set MFA Registration */
|
||||
public void setMFA_Registration_ID (int MFA_Registration_ID);
|
||||
|
||||
/** Get MFA Registration */
|
||||
public int getMFA_Registration_ID();
|
||||
|
||||
/** Column name MFA_Registration_UU */
|
||||
public static final String COLUMNNAME_MFA_Registration_UU = "MFA_Registration_UU";
|
||||
|
||||
/** Set MFA_Registration_UU */
|
||||
public void setMFA_Registration_UU (String MFA_Registration_UU);
|
||||
|
||||
/** Get MFA_Registration_UU */
|
||||
public String getMFA_Registration_UU();
|
||||
|
||||
/** Column name MFASecret */
|
||||
public static final String COLUMNNAME_MFASecret = "MFASecret";
|
||||
|
||||
/** Set MFA Secret.
|
||||
* Multi-factor Authentication Secret
|
||||
*/
|
||||
public void setMFASecret (String MFASecret);
|
||||
|
||||
/** Get MFA Secret.
|
||||
* Multi-factor Authentication Secret
|
||||
*/
|
||||
public String getMFASecret();
|
||||
|
||||
/** Column name MFAUnregisteredAt */
|
||||
public static final String COLUMNNAME_MFAUnregisteredAt = "MFAUnregisteredAt";
|
||||
|
||||
/** Set Unregistered at */
|
||||
public void setMFAUnregisteredAt (Timestamp MFAUnregisteredAt);
|
||||
|
||||
/** Get Unregistered at */
|
||||
public Timestamp getMFAUnregisteredAt();
|
||||
|
||||
/** Column name MFAValidatedAt */
|
||||
public static final String COLUMNNAME_MFAValidatedAt = "MFAValidatedAt";
|
||||
|
||||
/** Set Validated at */
|
||||
public void setMFAValidatedAt (Timestamp MFAValidatedAt);
|
||||
|
||||
/** Get Validated at */
|
||||
public Timestamp getMFAValidatedAt();
|
||||
|
||||
/** Column name Name */
|
||||
public static final String COLUMNNAME_Name = "Name";
|
||||
|
||||
/** Set Name.
|
||||
* Alphanumeric identifier of the entity
|
||||
*/
|
||||
public void setName (String Name);
|
||||
|
||||
/** Get Name.
|
||||
* Alphanumeric identifier of the entity
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/** Column name ParameterValue */
|
||||
public static final String COLUMNNAME_ParameterValue = "ParameterValue";
|
||||
|
||||
/** Set Parameter Value */
|
||||
public void setParameterValue (String ParameterValue);
|
||||
|
||||
/** Get Parameter Value */
|
||||
public String getParameterValue();
|
||||
|
||||
/** Column name Updated */
|
||||
public static final String COLUMNNAME_Updated = "Updated";
|
||||
|
||||
/** Get Updated.
|
||||
* Date this record was updated
|
||||
*/
|
||||
public Timestamp getUpdated();
|
||||
|
||||
/** Column name UpdatedBy */
|
||||
public static final String COLUMNNAME_UpdatedBy = "UpdatedBy";
|
||||
|
||||
/** Get Updated By.
|
||||
* User who updated this records
|
||||
*/
|
||||
public int getUpdatedBy();
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
||||
/** Generated Interface for MFA_Rule
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2
|
||||
*/
|
||||
public interface I_MFA_Rule
|
||||
{
|
||||
|
||||
/** TableName=MFA_Rule */
|
||||
public static final String Table_Name = "MFA_Rule";
|
||||
|
||||
/** AD_Table_ID=200276 */
|
||||
public static final int Table_ID = 200276;
|
||||
|
||||
KeyNamePair Model = new KeyNamePair(Table_ID, Table_Name);
|
||||
|
||||
/** AccessLevel = 6 - System - Client
|
||||
*/
|
||||
BigDecimal accessLevel = BigDecimal.valueOf(6);
|
||||
|
||||
/** Load Meta Data */
|
||||
|
||||
/** Column name AD_Client_ID */
|
||||
public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID";
|
||||
|
||||
/** Get Client.
|
||||
* Client/Tenant for this installation.
|
||||
*/
|
||||
public int getAD_Client_ID();
|
||||
|
||||
/** Column name AD_Org_ID */
|
||||
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";
|
||||
|
||||
/** Set Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public void setAD_Org_ID (int AD_Org_ID);
|
||||
|
||||
/** Get Organization.
|
||||
* Organizational entity within client
|
||||
*/
|
||||
public int getAD_Org_ID();
|
||||
|
||||
/** Column name Created */
|
||||
public static final String COLUMNNAME_Created = "Created";
|
||||
|
||||
/** Get Created.
|
||||
* Date this record was created
|
||||
*/
|
||||
public Timestamp getCreated();
|
||||
|
||||
/** Column name CreatedBy */
|
||||
public static final String COLUMNNAME_CreatedBy = "CreatedBy";
|
||||
|
||||
/** Get Created By.
|
||||
* User who created this records
|
||||
*/
|
||||
public int getCreatedBy();
|
||||
|
||||
/** Column name Help */
|
||||
public static final String COLUMNNAME_Help = "Help";
|
||||
|
||||
/** Set Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help);
|
||||
|
||||
/** Get Comment/Help.
|
||||
* Comment or Hint
|
||||
*/
|
||||
public String getHelp();
|
||||
|
||||
/** Column name IsActive */
|
||||
public static final String COLUMNNAME_IsActive = "IsActive";
|
||||
|
||||
/** Set Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public void setIsActive (boolean IsActive);
|
||||
|
||||
/** Get Active.
|
||||
* The record is active in the system
|
||||
*/
|
||||
public boolean isActive();
|
||||
|
||||
/** Column name MFA_Method_ID */
|
||||
public static final String COLUMNNAME_MFA_Method_ID = "MFA_Method_ID";
|
||||
|
||||
/** Set MFA Method.
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public void setMFA_Method_ID (int MFA_Method_ID);
|
||||
|
||||
/** Get MFA Method.
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public int getMFA_Method_ID();
|
||||
|
||||
public org.compiere.model.I_MFA_Method getMFA_Method() throws RuntimeException;
|
||||
|
||||
/** Column name MFA_Rule_ID */
|
||||
public static final String COLUMNNAME_MFA_Rule_ID = "MFA_Rule_ID";
|
||||
|
||||
/** Set MFA Rule.
|
||||
* Multi-factor Authentication Rule
|
||||
*/
|
||||
public void setMFA_Rule_ID (int MFA_Rule_ID);
|
||||
|
||||
/** Get MFA Rule.
|
||||
* Multi-factor Authentication Rule
|
||||
*/
|
||||
public int getMFA_Rule_ID();
|
||||
|
||||
/** Column name MFA_Rule_UU */
|
||||
public static final String COLUMNNAME_MFA_Rule_UU = "MFA_Rule_UU";
|
||||
|
||||
/** Set MFA_Rule_UU */
|
||||
public void setMFA_Rule_UU (String MFA_Rule_UU);
|
||||
|
||||
/** Get MFA_Rule_UU */
|
||||
public String getMFA_Rule_UU();
|
||||
|
||||
/** Column name Updated */
|
||||
public static final String COLUMNNAME_Updated = "Updated";
|
||||
|
||||
/** Get Updated.
|
||||
* Date this record was updated
|
||||
*/
|
||||
public Timestamp getUpdated();
|
||||
|
||||
/** Column name UpdatedBy */
|
||||
public static final String COLUMNNAME_UpdatedBy = "UpdatedBy";
|
||||
|
||||
/** Get Updated By.
|
||||
* User who updated this records
|
||||
*/
|
||||
public int getUpdatedBy();
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.adempiere.base.IServiceReferenceHolder;
|
||||
import org.adempiere.base.Service;
|
||||
import org.adempiere.base.ServiceQuery;
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.util.CCache;
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication Method
|
||||
*/
|
||||
public class MMFAMethod extends X_MFA_Method {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7954271872310037840L;
|
||||
|
||||
/**
|
||||
* Read/Create empty MFA Method
|
||||
*
|
||||
* @param ctx context
|
||||
* @param MFA_Method_ID ID
|
||||
* @param trxName transaction
|
||||
*/
|
||||
public MMFAMethod(Properties ctx, int MFA_Method_ID, String trxName) {
|
||||
super(ctx, MFA_Method_ID, trxName);
|
||||
} // MMFAMethod
|
||||
|
||||
/**
|
||||
* Read MFA Method from current row in ResultSet
|
||||
*
|
||||
* @param ctx context
|
||||
* @param rs ResultSet
|
||||
* @param trxName transaction
|
||||
*/
|
||||
public MMFAMethod(Properties ctx, ResultSet rs, String trxName) {
|
||||
super(ctx, rs, trxName);
|
||||
} // MMFAMethod
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@link IMFAMechanism}
|
||||
*/
|
||||
public IMFAMechanism getMFAMechanism() {
|
||||
ServiceQuery query = new ServiceQuery();
|
||||
String method = getMethod();
|
||||
if (method == null)
|
||||
throw new AdempiereException("No method");
|
||||
query.put("method", method);
|
||||
IMFAMechanism mechanism = getMFAMechanismService(query);
|
||||
if (mechanism == null)
|
||||
throw new AdempiereException("No MFA mechanism provider found");
|
||||
return mechanism;
|
||||
}
|
||||
|
||||
private static CCache<ServiceQuery, IServiceReferenceHolder<IMFAMechanism>> s_MFAMechanismReference = new CCache<>(null, "IMFAMechanism", 3, false);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param query
|
||||
* @return {@link IMFAMechanism}
|
||||
*/
|
||||
public static IMFAMechanism getMFAMechanismService(ServiceQuery query) {
|
||||
IMFAMechanism mechanism = null;
|
||||
IServiceReferenceHolder<IMFAMechanism> cache = s_MFAMechanismReference.get(query);
|
||||
if (cache != null) {
|
||||
mechanism = cache.getService();
|
||||
if (mechanism != null)
|
||||
return mechanism;
|
||||
else
|
||||
s_MFAMechanismReference.remove(query);
|
||||
}
|
||||
IServiceReferenceHolder<IMFAMechanism> serviceReference = Service.locator().locate(IMFAMechanism.class, query).getServiceReference();
|
||||
if (serviceReference != null) {
|
||||
mechanism = serviceReference.getService();
|
||||
if (mechanism != null)
|
||||
s_MFAMechanismReference.put(query, serviceReference);
|
||||
}
|
||||
return mechanism;
|
||||
}
|
||||
|
||||
} // MMFAMethod
|
|
@ -0,0 +1,94 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.compiere.util.Env;
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication Registered Device
|
||||
*/
|
||||
public class MMFARegisteredDevice extends X_MFA_RegisteredDevice {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7913538709234444407L;
|
||||
|
||||
/**
|
||||
* Read/Create empty MFA Registered Device
|
||||
*
|
||||
* @param ctx context
|
||||
* @param MFA_RegisteredDevice_ID ID
|
||||
* @param trxName transaction
|
||||
*/
|
||||
public MMFARegisteredDevice(Properties ctx, int MFA_RegisteredDevice_ID, String trxName) {
|
||||
super(ctx, MFA_RegisteredDevice_ID, trxName);
|
||||
} // MMFARegisteredDevice
|
||||
|
||||
/**
|
||||
* Read MFA Registered Device from current row in ResultSet
|
||||
*
|
||||
* @param ctx context
|
||||
* @param rs ResultSet
|
||||
* @param trxName transaction
|
||||
*/
|
||||
public MMFARegisteredDevice(Properties ctx, ResultSet rs, String trxName) {
|
||||
super(ctx, rs, trxName);
|
||||
} // MMFARegisteredDevice
|
||||
|
||||
/**
|
||||
* Validate if there is a non-expired device registered with that code
|
||||
* @param registerCookie
|
||||
* @return true if device is valid
|
||||
*/
|
||||
public static boolean isValid(String identifier) {
|
||||
final String where = "AD_User_ID=? AND MFADeviceIdentifier=? AND Expiration>SYSDATE";
|
||||
MMFARegisteredDevice rd = new Query(Env.getCtx(), Table_Name, where, null)
|
||||
.setParameters(Env.getAD_User_ID(Env.getCtx()), identifier)
|
||||
.setClient_ID()
|
||||
.setOnlyActiveRecords(true)
|
||||
.first();
|
||||
return (rd != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set User/Contact.
|
||||
* @param AD_User_ID
|
||||
* User within the system - Internal or Business Partner Contact
|
||||
* Overridden to allow saving System record (zero ID)
|
||||
*/
|
||||
@Override
|
||||
public void setAD_User_ID (int AD_User_ID)
|
||||
{
|
||||
if (AD_User_ID == 0)
|
||||
set_ValueNoCheck (COLUMNNAME_AD_User_ID, AD_User_ID);
|
||||
else
|
||||
super.setAD_User_ID(AD_User_ID);
|
||||
} //setAD_User_ID
|
||||
|
||||
} // MMFARegisteredDevice
|
|
@ -0,0 +1,208 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
|
||||
/**
|
||||
* Multi-factor Authentication Registration
|
||||
*/
|
||||
public class MMFARegistration extends X_MFA_Registration {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -2032862057961778934L;
|
||||
|
||||
/**
|
||||
* Read/Create empty MFA Registration
|
||||
*
|
||||
* @param ctx context
|
||||
* @param MFA_Registration_ID ID
|
||||
* @param trxName transaction
|
||||
*/
|
||||
public MMFARegistration(Properties ctx, int MFA_Registration_ID, String trxName) {
|
||||
super(ctx, MFA_Registration_ID, trxName);
|
||||
} // MMFARegistration
|
||||
|
||||
/**
|
||||
* Read MFA Registration from current row in ResultSet
|
||||
*
|
||||
* @param ctx context
|
||||
* @param rs ResultSet
|
||||
* @param trxName transaction
|
||||
*/
|
||||
public MMFARegistration(Properties ctx, ResultSet rs, String trxName) {
|
||||
super(ctx, rs, trxName);
|
||||
} // MMFARegistration
|
||||
|
||||
/**
|
||||
* Validate if a method is already registered for this user
|
||||
* @param method
|
||||
* @param prm
|
||||
* @return
|
||||
*/
|
||||
public static boolean alreadyExistsValid(MMFAMethod method, String prm) {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
params.add(Env.getAD_User_ID(method.getCtx()));
|
||||
params.add(method.getMFA_Method_ID());
|
||||
params.add(Env.getAD_Client_ID(method.getCtx()));
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT COUNT(*)"
|
||||
+ " FROM MFA_Registration"
|
||||
+ " WHERE AD_User_ID=?"
|
||||
+ " AND MFA_Method_ID=?"
|
||||
+ " AND IsValid='Y'"
|
||||
+ " AND AD_Client_ID=?"
|
||||
+ " AND IsActive='Y'");
|
||||
if (prm != null) {
|
||||
sql.append(" AND ParameterValue=?");
|
||||
params.add(prm);
|
||||
}
|
||||
int cnt = DB.getSQLValueEx(method.get_TrxName(), sql.toString(), params);
|
||||
return cnt != 0;
|
||||
}
|
||||
|
||||
public static void invalidatePreviousPending(MMFAMethod method, String prm, MMFARegistration reg) {
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
params.add(Env.getAD_User_ID(method.getCtx()));
|
||||
params.add(method.getMFA_Method_ID());
|
||||
params.add(Env.getAD_Client_ID(method.getCtx()));
|
||||
params.add(reg.getMFA_Registration_ID());
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("UPDATE MFA_Registration"
|
||||
+ " SET IsActive='N'"
|
||||
+ " WHERE AD_User_ID=?"
|
||||
+ " AND MFA_Method_ID=?"
|
||||
+ " AND AD_Client_ID=?"
|
||||
+ " AND IsValid='N'"
|
||||
+ " AND IsActive='Y'"
|
||||
+ " AND MFA_Registration_ID!=?");
|
||||
if (prm != null) {
|
||||
sql.append(" AND ParameterValue=?");
|
||||
params.add(prm);
|
||||
}
|
||||
DB.executeUpdateEx(sql.toString(), params.toArray(), method.get_TrxName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set record as preferred, and set all the others from this user as not preferred
|
||||
*/
|
||||
@Override
|
||||
public void setIsUserMFAPreferred(boolean IsUserMFAPreferred) {
|
||||
super.setIsUserMFAPreferred(IsUserMFAPreferred);
|
||||
if (IsUserMFAPreferred) {
|
||||
int userId = getAD_User_ID();
|
||||
int clientId = getAD_Client_ID();
|
||||
int regId = getMFA_Registration_ID();
|
||||
final String sql = ""
|
||||
+ "UPDATE MFA_Registration"
|
||||
+ " SET IsUserMFAPreferred='N'"
|
||||
+ " WHERE AD_User_ID=?"
|
||||
+ " AND AD_Client_ID=?"
|
||||
+ " AND IsUserMFAPreferred='Y'"
|
||||
+ " AND MFA_Registration_ID!=?";
|
||||
DB.executeUpdateEx(sql, new Object[] {userId, clientId, regId}, get_TrxName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the valid registrations from this user
|
||||
* @return
|
||||
*/
|
||||
public static List<MMFARegistration> getValidRegistrationsFromUser() {
|
||||
final String where = "IsValid ='Y' AND AD_User_ID=? AND AD_Client_ID IN (0,?)";
|
||||
List<MMFARegistration> ret = new Query(Env.getCtx(), Table_Name, where, null)
|
||||
.setParameters(Env.getAD_User_ID(Env.getCtx()), Env.getAD_Client_ID(Env.getCtx()))
|
||||
.setOnlyActiveRecords(true)
|
||||
.setOrderBy("IsUserMFAPreferred DESC, Name")
|
||||
.list();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user has valid registration mechanisms
|
||||
* @return
|
||||
*/
|
||||
public static boolean userHasValidRegistration() {
|
||||
final String sql = ""
|
||||
+ "SELECT COUNT(*)"
|
||||
+ " FROM MFA_Registration"
|
||||
+ " WHERE IsActive='Y'"
|
||||
+ " AND IsValid ='Y'"
|
||||
+ " AND AD_User_ID=?"
|
||||
+ " AND AD_Client_ID IN (0,?)";
|
||||
int cnt = DB.getSQLValueEx(null, sql, Env.getAD_User_ID(Env.getCtx()), Env.getAD_Client_ID(Env.getCtx()));
|
||||
return cnt > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a validation code using the registered method
|
||||
* @param reg
|
||||
* @return
|
||||
*/
|
||||
public String generateValidationCode(MMFARegistration reg) {
|
||||
MMFAMethod method = new MMFAMethod(getCtx(), getMFA_Method_ID(), get_TrxName());
|
||||
IMFAMechanism mechanism = method.getMFAMechanism();
|
||||
String msg = mechanism.generateValidationCode(reg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the code using the registered method
|
||||
* @param reg
|
||||
* @param code
|
||||
* @param setPreferred
|
||||
* @return
|
||||
*/
|
||||
public String validateCode(MMFARegistration reg, String code, boolean setPreferred) {
|
||||
MMFAMethod method = new MMFAMethod(getCtx(), getMFA_Method_ID(), get_TrxName());
|
||||
IMFAMechanism mechanism = method.getMFAMechanism();
|
||||
String msg = mechanism.validateCode(reg, code, setPreferred);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set User/Contact.
|
||||
* @param AD_User_ID
|
||||
* User within the system - Internal or Business Partner Contact
|
||||
* Overridden to allow saving System record (zero ID)
|
||||
*/
|
||||
@Override
|
||||
public void setAD_User_ID (int AD_User_ID)
|
||||
{
|
||||
if (AD_User_ID == 0)
|
||||
set_ValueNoCheck (COLUMNNAME_AD_User_ID, AD_User_ID);
|
||||
else
|
||||
super.setAD_User_ID(AD_User_ID);
|
||||
} //setAD_User_ID
|
||||
|
||||
} // MMFARegistration
|
|
@ -43,7 +43,7 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8581992138870649241L;
|
||||
private static final long serialVersionUID = 2454757193097243912L;
|
||||
|
||||
public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION";
|
||||
public static final String ALERT_SEND_ATTACHMENT_AS_XLS = "ALERT_SEND_ATTACHMENT_AS_XLS";
|
||||
|
@ -124,6 +124,8 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
public static final String MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER = "MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER";
|
||||
public static final String MAX_TEXT_LENGTH_ON_GRID_VIEW = "MAX_TEXT_LENGTH_ON_GRID_VIEW";
|
||||
public static final String MENU_INFOUPDATER_SLEEP_MS = "MENU_INFOUPDATER_SLEEP_MS";
|
||||
public static final String MFA_NTP_TIMEOUT_IN_MILLISECONDS = "MFA_NTP_TIMEOUT_IN_MILLISECONDS";
|
||||
public static final String MFA_REGISTERED_DEVICE_EXPIRATION_DAYS = "MFA_REGISTERED_DEVICE_EXPIRATION_DAYS";
|
||||
public static final String MONITOR_INITIAL_WAIT_FOR_CLUSTER_IN_SECONDS = "MONITOR_INITIAL_WAIT_FOR_CLUSTER_IN_SECONDS";
|
||||
public static final String MONITOR_MAX_WAIT_FOR_CLUSTER_IN_SECONDS = "MONITOR_MAX_WAIT_FOR_CLUSTER_IN_SECONDS";
|
||||
public static final String MFG_ValidateCostsDifferenceOnCreate = "MFG_ValidateCostsDifferenceOnCreate";
|
||||
|
|
|
@ -60,6 +60,7 @@ public class SystemIDs
|
|||
public final static int FORM_REPORT_WIZARD = 200002;
|
||||
public final static int FORM_SETUP_WIZARD = 200000;
|
||||
public final static int FORM_ADD_AUTHORIZATION = 200016;
|
||||
public final static int FORM_MFA_REGISTER = 200017;
|
||||
|
||||
public final static int MENU_NOTICE = 233;
|
||||
|
||||
|
|
|
@ -0,0 +1,355 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
/** Generated Model - DO NOT CHANGE */
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Properties;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
||||
/** Generated Model for MFA_Method
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2 - $Id$ */
|
||||
public class X_MFA_Method extends PO implements I_MFA_Method, I_Persistent
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20210605L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_MFA_Method (Properties ctx, int MFA_Method_ID, String trxName)
|
||||
{
|
||||
super (ctx, MFA_Method_ID, trxName);
|
||||
/** if (MFA_Method_ID == 0)
|
||||
{
|
||||
setMethod (null);
|
||||
setMFA_Method_ID (0);
|
||||
setName (null);
|
||||
} */
|
||||
}
|
||||
|
||||
/** Load Constructor */
|
||||
public X_MFA_Method (Properties ctx, ResultSet rs, String trxName)
|
||||
{
|
||||
super (ctx, rs, trxName);
|
||||
}
|
||||
|
||||
/** AccessLevel
|
||||
* @return 4 - System
|
||||
*/
|
||||
protected int get_AccessLevel()
|
||||
{
|
||||
return accessLevel.intValue();
|
||||
}
|
||||
|
||||
/** Load Meta Data */
|
||||
protected POInfo initPO (Properties ctx)
|
||||
{
|
||||
POInfo poi = POInfo.getPOInfo (ctx, Table_ID, get_TrxName());
|
||||
return poi;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ("X_MFA_Method[")
|
||||
.append(get_ID()).append(",Name=").append(getName()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** Set Description.
|
||||
@param Description
|
||||
Optional short description of the record
|
||||
*/
|
||||
public void setDescription (String Description)
|
||||
{
|
||||
set_Value (COLUMNNAME_Description, Description);
|
||||
}
|
||||
|
||||
/** Get Description.
|
||||
@return Optional short description of the record
|
||||
*/
|
||||
public String getDescription ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Description);
|
||||
}
|
||||
|
||||
/** Set Expire in Minutes.
|
||||
@param ExpireInMinutes Expire in Minutes */
|
||||
public void setExpireInMinutes (int ExpireInMinutes)
|
||||
{
|
||||
set_Value (COLUMNNAME_ExpireInMinutes, Integer.valueOf(ExpireInMinutes));
|
||||
}
|
||||
|
||||
/** Get Expire in Minutes.
|
||||
@return Expire in Minutes */
|
||||
public int getExpireInMinutes ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_ExpireInMinutes);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set Comment/Help.
|
||||
@param Help
|
||||
Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help)
|
||||
{
|
||||
set_Value (COLUMNNAME_Help, Help);
|
||||
}
|
||||
|
||||
/** Get Comment/Help.
|
||||
@return Comment or Hint
|
||||
*/
|
||||
public String getHelp ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Help);
|
||||
}
|
||||
|
||||
/** Method AD_Reference_ID=200187 */
|
||||
public static final int METHOD_AD_Reference_ID=200187;
|
||||
/** Time-Based One-Time Password = TOTP */
|
||||
public static final String METHOD_Time_BasedOne_TimePassword = "TOTP";
|
||||
/** EMail = EMail */
|
||||
public static final String METHOD_EMail = "EMail";
|
||||
/** Set Method.
|
||||
@param Method Method */
|
||||
public void setMethod (String Method)
|
||||
{
|
||||
|
||||
set_Value (COLUMNNAME_Method, Method);
|
||||
}
|
||||
|
||||
/** Get Method.
|
||||
@return Method */
|
||||
public String getMethod ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Method);
|
||||
}
|
||||
|
||||
/** Set Allowed Time Period Discrepancy.
|
||||
@param MFAAllowedTimeDiscrepancy Allowed Time Period Discrepancy */
|
||||
public void setMFAAllowedTimeDiscrepancy (int MFAAllowedTimeDiscrepancy)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFAAllowedTimeDiscrepancy, Integer.valueOf(MFAAllowedTimeDiscrepancy));
|
||||
}
|
||||
|
||||
/** Get Allowed Time Period Discrepancy.
|
||||
@return Allowed Time Period Discrepancy */
|
||||
public int getMFAAllowedTimeDiscrepancy ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFAAllowedTimeDiscrepancy);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
public org.compiere.model.I_AD_Element getMFA_ElementPrm() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_AD_Element)MTable.get(getCtx(), org.compiere.model.I_AD_Element.Table_Name)
|
||||
.getPO(getMFA_ElementPrm_ID(), get_TrxName()); }
|
||||
|
||||
/** Set Parameter Element.
|
||||
@param MFA_ElementPrm_ID Parameter Element */
|
||||
public void setMFA_ElementPrm_ID (int MFA_ElementPrm_ID)
|
||||
{
|
||||
if (MFA_ElementPrm_ID < 1)
|
||||
set_Value (COLUMNNAME_MFA_ElementPrm_ID, null);
|
||||
else
|
||||
set_Value (COLUMNNAME_MFA_ElementPrm_ID, Integer.valueOf(MFA_ElementPrm_ID));
|
||||
}
|
||||
|
||||
/** Get Parameter Element.
|
||||
@return Parameter Element */
|
||||
public int getMFA_ElementPrm_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_ElementPrm_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set Issuer.
|
||||
@param MFAIssuer Issuer */
|
||||
public void setMFAIssuer (String MFAIssuer)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFAIssuer, MFAIssuer);
|
||||
}
|
||||
|
||||
/** Get Issuer.
|
||||
@return Issuer */
|
||||
public String getMFAIssuer ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFAIssuer);
|
||||
}
|
||||
|
||||
/** Set MFA Method.
|
||||
@param MFA_Method_ID
|
||||
Multi-factor Authentication Method
|
||||
*/
|
||||
public void setMFA_Method_ID (int MFA_Method_ID)
|
||||
{
|
||||
if (MFA_Method_ID < 1)
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Method_ID, null);
|
||||
else
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Method_ID, Integer.valueOf(MFA_Method_ID));
|
||||
}
|
||||
|
||||
/** Get MFA Method.
|
||||
@return Multi-factor Authentication Method
|
||||
*/
|
||||
public int getMFA_Method_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_Method_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set MFA_Method_UU.
|
||||
@param MFA_Method_UU MFA_Method_UU */
|
||||
public void setMFA_Method_UU (String MFA_Method_UU)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFA_Method_UU, MFA_Method_UU);
|
||||
}
|
||||
|
||||
/** Get MFA_Method_UU.
|
||||
@return MFA_Method_UU */
|
||||
public String getMFA_Method_UU ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFA_Method_UU);
|
||||
}
|
||||
|
||||
/** MFATimeProvider AD_Reference_ID=200189 */
|
||||
public static final int MFATIMEPROVIDER_AD_Reference_ID=200189;
|
||||
/** System = S */
|
||||
public static final String MFATIMEPROVIDER_System = "S";
|
||||
/** Ntp = N */
|
||||
public static final String MFATIMEPROVIDER_Ntp = "N";
|
||||
/** Set Time Provider.
|
||||
@param MFATimeProvider Time Provider */
|
||||
public void setMFATimeProvider (String MFATimeProvider)
|
||||
{
|
||||
|
||||
set_Value (COLUMNNAME_MFATimeProvider, MFATimeProvider);
|
||||
}
|
||||
|
||||
/** Get Time Provider.
|
||||
@return Time Provider */
|
||||
public String getMFATimeProvider ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFATimeProvider);
|
||||
}
|
||||
|
||||
/** Set Time Server.
|
||||
@param MFATimeServer Time Server */
|
||||
public void setMFATimeServer (String MFATimeServer)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFATimeServer, MFATimeServer);
|
||||
}
|
||||
|
||||
/** Get Time Server.
|
||||
@return Time Server */
|
||||
public String getMFATimeServer ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFATimeServer);
|
||||
}
|
||||
|
||||
/** MFAType AD_Reference_ID=200188 */
|
||||
public static final int MFATYPE_AD_Reference_ID=200188;
|
||||
/** Something you Know = K */
|
||||
public static final String MFATYPE_SomethingYouKnow = "K";
|
||||
/** Something you Have = H */
|
||||
public static final String MFATYPE_SomethingYouHave = "H";
|
||||
/** Something you Are (Biometrics) = A */
|
||||
public static final String MFATYPE_SomethingYouAreBiometrics = "A";
|
||||
/** Location = L */
|
||||
public static final String MFATYPE_Location = "L";
|
||||
/** Set MFA Type.
|
||||
@param MFAType
|
||||
Multi-factor authentication type (Something you Know/Have/Are, Location)
|
||||
*/
|
||||
public void setMFAType (String MFAType)
|
||||
{
|
||||
|
||||
set_Value (COLUMNNAME_MFAType, MFAType);
|
||||
}
|
||||
|
||||
/** Get MFA Type.
|
||||
@return Multi-factor authentication type (Something you Know/Have/Are, Location)
|
||||
*/
|
||||
public String getMFAType ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFAType);
|
||||
}
|
||||
|
||||
/** Set Name.
|
||||
@param Name
|
||||
Alphanumeric identifier of the entity
|
||||
*/
|
||||
public void setName (String Name)
|
||||
{
|
||||
set_Value (COLUMNNAME_Name, Name);
|
||||
}
|
||||
|
||||
/** Get Name.
|
||||
@return Alphanumeric identifier of the entity
|
||||
*/
|
||||
public String getName ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Name);
|
||||
}
|
||||
|
||||
/** Get Record ID/ColumnName
|
||||
@return ID/ColumnName pair
|
||||
*/
|
||||
public KeyNamePair getKeyNamePair()
|
||||
{
|
||||
return new KeyNamePair(get_ID(), getName());
|
||||
}
|
||||
|
||||
public org.compiere.model.I_R_MailText getR_MailText() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_R_MailText)MTable.get(getCtx(), org.compiere.model.I_R_MailText.Table_Name)
|
||||
.getPO(getR_MailText_ID(), get_TrxName()); }
|
||||
|
||||
/** Set Mail Template.
|
||||
@param R_MailText_ID
|
||||
Text templates for mailings
|
||||
*/
|
||||
public void setR_MailText_ID (int R_MailText_ID)
|
||||
{
|
||||
if (R_MailText_ID < 1)
|
||||
set_Value (COLUMNNAME_R_MailText_ID, null);
|
||||
else
|
||||
set_Value (COLUMNNAME_R_MailText_ID, Integer.valueOf(R_MailText_ID));
|
||||
}
|
||||
|
||||
/** Get Mail Template.
|
||||
@return Text templates for mailings
|
||||
*/
|
||||
public int getR_MailText_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_R_MailText_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
/** Generated Model - DO NOT CHANGE */
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Properties;
|
||||
|
||||
/** Generated Model for MFA_RegisteredDevice
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2 - $Id$ */
|
||||
public class X_MFA_RegisteredDevice extends PO implements I_MFA_RegisteredDevice, I_Persistent
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20210605L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_MFA_RegisteredDevice (Properties ctx, int MFA_RegisteredDevice_ID, String trxName)
|
||||
{
|
||||
super (ctx, MFA_RegisteredDevice_ID, trxName);
|
||||
/** if (MFA_RegisteredDevice_ID == 0)
|
||||
{
|
||||
setAD_User_ID (0);
|
||||
setMFADeviceIdentifier (null);
|
||||
setMFA_RegisteredDevice_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
/** Load Constructor */
|
||||
public X_MFA_RegisteredDevice (Properties ctx, ResultSet rs, String trxName)
|
||||
{
|
||||
super (ctx, rs, trxName);
|
||||
}
|
||||
|
||||
/** AccessLevel
|
||||
* @return 6 - System - Client
|
||||
*/
|
||||
protected int get_AccessLevel()
|
||||
{
|
||||
return accessLevel.intValue();
|
||||
}
|
||||
|
||||
/** Load Meta Data */
|
||||
protected POInfo initPO (Properties ctx)
|
||||
{
|
||||
POInfo poi = POInfo.getPOInfo (ctx, Table_ID, get_TrxName());
|
||||
return poi;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ("X_MFA_RegisteredDevice[")
|
||||
.append(get_ID()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public org.compiere.model.I_AD_User getAD_User() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_AD_User)MTable.get(getCtx(), org.compiere.model.I_AD_User.Table_Name)
|
||||
.getPO(getAD_User_ID(), get_TrxName()); }
|
||||
|
||||
/** Set User/Contact.
|
||||
@param AD_User_ID
|
||||
User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public void setAD_User_ID (int AD_User_ID)
|
||||
{
|
||||
if (AD_User_ID < 1)
|
||||
set_Value (COLUMNNAME_AD_User_ID, null);
|
||||
else
|
||||
set_Value (COLUMNNAME_AD_User_ID, Integer.valueOf(AD_User_ID));
|
||||
}
|
||||
|
||||
/** Get User/Contact.
|
||||
@return User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public int getAD_User_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_AD_User_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set Expire On.
|
||||
@param Expiration
|
||||
Expire On
|
||||
*/
|
||||
public void setExpiration (Timestamp Expiration)
|
||||
{
|
||||
set_Value (COLUMNNAME_Expiration, Expiration);
|
||||
}
|
||||
|
||||
/** Get Expire On.
|
||||
@return Expire On
|
||||
*/
|
||||
public Timestamp getExpiration ()
|
||||
{
|
||||
return (Timestamp)get_Value(COLUMNNAME_Expiration);
|
||||
}
|
||||
|
||||
/** Set Comment/Help.
|
||||
@param Help
|
||||
Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help)
|
||||
{
|
||||
set_Value (COLUMNNAME_Help, Help);
|
||||
}
|
||||
|
||||
/** Get Comment/Help.
|
||||
@return Comment or Hint
|
||||
*/
|
||||
public String getHelp ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Help);
|
||||
}
|
||||
|
||||
/** Set MFA Device Identifier.
|
||||
@param MFADeviceIdentifier
|
||||
Multi-factor Authentication Device Identifier
|
||||
*/
|
||||
public void setMFADeviceIdentifier (String MFADeviceIdentifier)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFADeviceIdentifier, MFADeviceIdentifier);
|
||||
}
|
||||
|
||||
/** Get MFA Device Identifier.
|
||||
@return Multi-factor Authentication Device Identifier
|
||||
*/
|
||||
public String getMFADeviceIdentifier ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFADeviceIdentifier);
|
||||
}
|
||||
|
||||
/** Set MFA Registered Device.
|
||||
@param MFA_RegisteredDevice_ID MFA Registered Device */
|
||||
public void setMFA_RegisteredDevice_ID (int MFA_RegisteredDevice_ID)
|
||||
{
|
||||
if (MFA_RegisteredDevice_ID < 1)
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_RegisteredDevice_ID, null);
|
||||
else
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_RegisteredDevice_ID, Integer.valueOf(MFA_RegisteredDevice_ID));
|
||||
}
|
||||
|
||||
/** Get MFA Registered Device.
|
||||
@return MFA Registered Device */
|
||||
public int getMFA_RegisteredDevice_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_RegisteredDevice_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set MFA_RegisteredDevice_UU.
|
||||
@param MFA_RegisteredDevice_UU MFA_RegisteredDevice_UU */
|
||||
public void setMFA_RegisteredDevice_UU (String MFA_RegisteredDevice_UU)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFA_RegisteredDevice_UU, MFA_RegisteredDevice_UU);
|
||||
}
|
||||
|
||||
/** Get MFA_RegisteredDevice_UU.
|
||||
@return MFA_RegisteredDevice_UU */
|
||||
public String getMFA_RegisteredDevice_UU ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFA_RegisteredDevice_UU);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
/** Generated Model - DO NOT CHANGE */
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Properties;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
||||
/** Generated Model for MFA_Registration
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2 - $Id$ */
|
||||
public class X_MFA_Registration extends PO implements I_MFA_Registration, I_Persistent
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20210607L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_MFA_Registration (Properties ctx, int MFA_Registration_ID, String trxName)
|
||||
{
|
||||
super (ctx, MFA_Registration_ID, trxName);
|
||||
/** if (MFA_Registration_ID == 0)
|
||||
{
|
||||
setAD_User_ID (0);
|
||||
setIsUserMFAPreferred (false);
|
||||
// N
|
||||
setIsValid (false);
|
||||
// N
|
||||
setMFA_Method_ID (0);
|
||||
setMFA_Registration_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
/** Load Constructor */
|
||||
public X_MFA_Registration (Properties ctx, ResultSet rs, String trxName)
|
||||
{
|
||||
super (ctx, rs, trxName);
|
||||
}
|
||||
|
||||
/** AccessLevel
|
||||
* @return 6 - System - Client
|
||||
*/
|
||||
protected int get_AccessLevel()
|
||||
{
|
||||
return accessLevel.intValue();
|
||||
}
|
||||
|
||||
/** Load Meta Data */
|
||||
protected POInfo initPO (Properties ctx)
|
||||
{
|
||||
POInfo poi = POInfo.getPOInfo (ctx, Table_ID, get_TrxName());
|
||||
return poi;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ("X_MFA_Registration[")
|
||||
.append(get_ID()).append(",Name=").append(getName()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public org.compiere.model.I_AD_User getAD_User() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_AD_User)MTable.get(getCtx(), org.compiere.model.I_AD_User.Table_Name)
|
||||
.getPO(getAD_User_ID(), get_TrxName()); }
|
||||
|
||||
/** Set User/Contact.
|
||||
@param AD_User_ID
|
||||
User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public void setAD_User_ID (int AD_User_ID)
|
||||
{
|
||||
if (AD_User_ID < 1)
|
||||
set_Value (COLUMNNAME_AD_User_ID, null);
|
||||
else
|
||||
set_Value (COLUMNNAME_AD_User_ID, Integer.valueOf(AD_User_ID));
|
||||
}
|
||||
|
||||
/** Get User/Contact.
|
||||
@return User within the system - Internal or Business Partner Contact
|
||||
*/
|
||||
public int getAD_User_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_AD_User_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set Expire On.
|
||||
@param Expiration
|
||||
Expire On
|
||||
*/
|
||||
public void setExpiration (Timestamp Expiration)
|
||||
{
|
||||
set_Value (COLUMNNAME_Expiration, Expiration);
|
||||
}
|
||||
|
||||
/** Get Expire On.
|
||||
@return Expire On
|
||||
*/
|
||||
public Timestamp getExpiration ()
|
||||
{
|
||||
return (Timestamp)get_Value(COLUMNNAME_Expiration);
|
||||
}
|
||||
|
||||
/** Set Failed Login Count.
|
||||
@param FailedLoginCount Failed Login Count */
|
||||
public void setFailedLoginCount (int FailedLoginCount)
|
||||
{
|
||||
set_ValueNoCheck (COLUMNNAME_FailedLoginCount, Integer.valueOf(FailedLoginCount));
|
||||
}
|
||||
|
||||
/** Get Failed Login Count.
|
||||
@return Failed Login Count */
|
||||
public int getFailedLoginCount ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_FailedLoginCount);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set Comment/Help.
|
||||
@param Help
|
||||
Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help)
|
||||
{
|
||||
set_Value (COLUMNNAME_Help, Help);
|
||||
}
|
||||
|
||||
/** Get Comment/Help.
|
||||
@return Comment or Hint
|
||||
*/
|
||||
public String getHelp ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Help);
|
||||
}
|
||||
|
||||
/** Set Preferred.
|
||||
@param IsUserMFAPreferred Preferred */
|
||||
public void setIsUserMFAPreferred (boolean IsUserMFAPreferred)
|
||||
{
|
||||
set_Value (COLUMNNAME_IsUserMFAPreferred, Boolean.valueOf(IsUserMFAPreferred));
|
||||
}
|
||||
|
||||
/** Get Preferred.
|
||||
@return Preferred */
|
||||
public boolean isUserMFAPreferred ()
|
||||
{
|
||||
Object oo = get_Value(COLUMNNAME_IsUserMFAPreferred);
|
||||
if (oo != null)
|
||||
{
|
||||
if (oo instanceof Boolean)
|
||||
return ((Boolean)oo).booleanValue();
|
||||
return "Y".equals(oo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Set Valid.
|
||||
@param IsValid
|
||||
Element is valid
|
||||
*/
|
||||
public void setIsValid (boolean IsValid)
|
||||
{
|
||||
set_Value (COLUMNNAME_IsValid, Boolean.valueOf(IsValid));
|
||||
}
|
||||
|
||||
/** Get Valid.
|
||||
@return Element is valid
|
||||
*/
|
||||
public boolean isValid ()
|
||||
{
|
||||
Object oo = get_Value(COLUMNNAME_IsValid);
|
||||
if (oo != null)
|
||||
{
|
||||
if (oo instanceof Boolean)
|
||||
return ((Boolean)oo).booleanValue();
|
||||
return "Y".equals(oo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Set Last Failure.
|
||||
@param LastFailure Last Failure */
|
||||
public void setLastFailure (Timestamp LastFailure)
|
||||
{
|
||||
set_Value (COLUMNNAME_LastFailure, LastFailure);
|
||||
}
|
||||
|
||||
/** Get Last Failure.
|
||||
@return Last Failure */
|
||||
public Timestamp getLastFailure ()
|
||||
{
|
||||
return (Timestamp)get_Value(COLUMNNAME_LastFailure);
|
||||
}
|
||||
|
||||
/** Set Last Success.
|
||||
@param LastSuccess Last Success */
|
||||
public void setLastSuccess (Timestamp LastSuccess)
|
||||
{
|
||||
set_Value (COLUMNNAME_LastSuccess, LastSuccess);
|
||||
}
|
||||
|
||||
/** Get Last Success.
|
||||
@return Last Success */
|
||||
public Timestamp getLastSuccess ()
|
||||
{
|
||||
return (Timestamp)get_Value(COLUMNNAME_LastSuccess);
|
||||
}
|
||||
|
||||
/** Set Last MFA Secret.
|
||||
@param MFALastSecret Last MFA Secret */
|
||||
public void setMFALastSecret (String MFALastSecret)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFALastSecret, MFALastSecret);
|
||||
}
|
||||
|
||||
/** Get Last MFA Secret.
|
||||
@return Last MFA Secret */
|
||||
public String getMFALastSecret ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFALastSecret);
|
||||
}
|
||||
|
||||
public org.compiere.model.I_MFA_Method getMFA_Method() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_MFA_Method)MTable.get(getCtx(), org.compiere.model.I_MFA_Method.Table_Name)
|
||||
.getPO(getMFA_Method_ID(), get_TrxName()); }
|
||||
|
||||
/** Set MFA Method.
|
||||
@param MFA_Method_ID
|
||||
Multi-factor Authentication Method
|
||||
*/
|
||||
public void setMFA_Method_ID (int MFA_Method_ID)
|
||||
{
|
||||
if (MFA_Method_ID < 1)
|
||||
set_Value (COLUMNNAME_MFA_Method_ID, null);
|
||||
else
|
||||
set_Value (COLUMNNAME_MFA_Method_ID, Integer.valueOf(MFA_Method_ID));
|
||||
}
|
||||
|
||||
/** Get MFA Method.
|
||||
@return Multi-factor Authentication Method
|
||||
*/
|
||||
public int getMFA_Method_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_Method_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set MFA Registration.
|
||||
@param MFA_Registration_ID MFA Registration */
|
||||
public void setMFA_Registration_ID (int MFA_Registration_ID)
|
||||
{
|
||||
if (MFA_Registration_ID < 1)
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Registration_ID, null);
|
||||
else
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Registration_ID, Integer.valueOf(MFA_Registration_ID));
|
||||
}
|
||||
|
||||
/** Get MFA Registration.
|
||||
@return MFA Registration */
|
||||
public int getMFA_Registration_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_Registration_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set MFA_Registration_UU.
|
||||
@param MFA_Registration_UU MFA_Registration_UU */
|
||||
public void setMFA_Registration_UU (String MFA_Registration_UU)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFA_Registration_UU, MFA_Registration_UU);
|
||||
}
|
||||
|
||||
/** Get MFA_Registration_UU.
|
||||
@return MFA_Registration_UU */
|
||||
public String getMFA_Registration_UU ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFA_Registration_UU);
|
||||
}
|
||||
|
||||
/** Set MFA Secret.
|
||||
@param MFASecret
|
||||
Multi-factor Authentication Secret
|
||||
*/
|
||||
public void setMFASecret (String MFASecret)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFASecret, MFASecret);
|
||||
}
|
||||
|
||||
/** Get MFA Secret.
|
||||
@return Multi-factor Authentication Secret
|
||||
*/
|
||||
public String getMFASecret ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFASecret);
|
||||
}
|
||||
|
||||
/** Set Unregistered at.
|
||||
@param MFAUnregisteredAt Unregistered at */
|
||||
public void setMFAUnregisteredAt (Timestamp MFAUnregisteredAt)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFAUnregisteredAt, MFAUnregisteredAt);
|
||||
}
|
||||
|
||||
/** Get Unregistered at.
|
||||
@return Unregistered at */
|
||||
public Timestamp getMFAUnregisteredAt ()
|
||||
{
|
||||
return (Timestamp)get_Value(COLUMNNAME_MFAUnregisteredAt);
|
||||
}
|
||||
|
||||
/** Set Validated at.
|
||||
@param MFAValidatedAt Validated at */
|
||||
public void setMFAValidatedAt (Timestamp MFAValidatedAt)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFAValidatedAt, MFAValidatedAt);
|
||||
}
|
||||
|
||||
/** Get Validated at.
|
||||
@return Validated at */
|
||||
public Timestamp getMFAValidatedAt ()
|
||||
{
|
||||
return (Timestamp)get_Value(COLUMNNAME_MFAValidatedAt);
|
||||
}
|
||||
|
||||
/** Set Name.
|
||||
@param Name
|
||||
Alphanumeric identifier of the entity
|
||||
*/
|
||||
public void setName (String Name)
|
||||
{
|
||||
set_Value (COLUMNNAME_Name, Name);
|
||||
}
|
||||
|
||||
/** Get Name.
|
||||
@return Alphanumeric identifier of the entity
|
||||
*/
|
||||
public String getName ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Name);
|
||||
}
|
||||
|
||||
/** Get Record ID/ColumnName
|
||||
@return ID/ColumnName pair
|
||||
*/
|
||||
public KeyNamePair getKeyNamePair()
|
||||
{
|
||||
return new KeyNamePair(get_ID(), getName());
|
||||
}
|
||||
|
||||
/** Set Parameter Value.
|
||||
@param ParameterValue Parameter Value */
|
||||
public void setParameterValue (String ParameterValue)
|
||||
{
|
||||
set_Value (COLUMNNAME_ParameterValue, ParameterValue);
|
||||
}
|
||||
|
||||
/** Get Parameter Value.
|
||||
@return Parameter Value */
|
||||
public String getParameterValue ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_ParameterValue);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/******************************************************************************
|
||||
* Product: iDempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2012 ComPiere, Inc. All Rights Reserved. *
|
||||
* This program is free software, you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program is distributed in the hope *
|
||||
* that it will be useful, but WITHOUT ANY WARRANTY, without even the implied *
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* You should have received a copy of the GNU General Public License along *
|
||||
* with this program, if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
/** Generated Model - DO NOT CHANGE */
|
||||
package org.compiere.model;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Properties;
|
||||
|
||||
/** Generated Model for MFA_Rule
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 8.2 - $Id$ */
|
||||
public class X_MFA_Rule extends PO implements I_MFA_Rule, I_Persistent
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20210605L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_MFA_Rule (Properties ctx, int MFA_Rule_ID, String trxName)
|
||||
{
|
||||
super (ctx, MFA_Rule_ID, trxName);
|
||||
/** if (MFA_Rule_ID == 0)
|
||||
{
|
||||
setMFA_Method_ID (0);
|
||||
setMFA_Rule_ID (0);
|
||||
} */
|
||||
}
|
||||
|
||||
/** Load Constructor */
|
||||
public X_MFA_Rule (Properties ctx, ResultSet rs, String trxName)
|
||||
{
|
||||
super (ctx, rs, trxName);
|
||||
}
|
||||
|
||||
/** AccessLevel
|
||||
* @return 6 - System - Client
|
||||
*/
|
||||
protected int get_AccessLevel()
|
||||
{
|
||||
return accessLevel.intValue();
|
||||
}
|
||||
|
||||
/** Load Meta Data */
|
||||
protected POInfo initPO (Properties ctx)
|
||||
{
|
||||
POInfo poi = POInfo.getPOInfo (ctx, Table_ID, get_TrxName());
|
||||
return poi;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ("X_MFA_Rule[")
|
||||
.append(get_ID()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** Set Comment/Help.
|
||||
@param Help
|
||||
Comment or Hint
|
||||
*/
|
||||
public void setHelp (String Help)
|
||||
{
|
||||
set_Value (COLUMNNAME_Help, Help);
|
||||
}
|
||||
|
||||
/** Get Comment/Help.
|
||||
@return Comment or Hint
|
||||
*/
|
||||
public String getHelp ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_Help);
|
||||
}
|
||||
|
||||
public org.compiere.model.I_MFA_Method getMFA_Method() throws RuntimeException
|
||||
{
|
||||
return (org.compiere.model.I_MFA_Method)MTable.get(getCtx(), org.compiere.model.I_MFA_Method.Table_Name)
|
||||
.getPO(getMFA_Method_ID(), get_TrxName()); }
|
||||
|
||||
/** Set MFA Method.
|
||||
@param MFA_Method_ID
|
||||
Multi-factor Authentication Method
|
||||
*/
|
||||
public void setMFA_Method_ID (int MFA_Method_ID)
|
||||
{
|
||||
if (MFA_Method_ID < 1)
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Method_ID, null);
|
||||
else
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Method_ID, Integer.valueOf(MFA_Method_ID));
|
||||
}
|
||||
|
||||
/** Get MFA Method.
|
||||
@return Multi-factor Authentication Method
|
||||
*/
|
||||
public int getMFA_Method_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_Method_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set MFA Rule.
|
||||
@param MFA_Rule_ID
|
||||
Multi-factor Authentication Rule
|
||||
*/
|
||||
public void setMFA_Rule_ID (int MFA_Rule_ID)
|
||||
{
|
||||
if (MFA_Rule_ID < 1)
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Rule_ID, null);
|
||||
else
|
||||
set_ValueNoCheck (COLUMNNAME_MFA_Rule_ID, Integer.valueOf(MFA_Rule_ID));
|
||||
}
|
||||
|
||||
/** Get MFA Rule.
|
||||
@return Multi-factor Authentication Rule
|
||||
*/
|
||||
public int getMFA_Rule_ID ()
|
||||
{
|
||||
Integer ii = (Integer)get_Value(COLUMNNAME_MFA_Rule_ID);
|
||||
if (ii == null)
|
||||
return 0;
|
||||
return ii.intValue();
|
||||
}
|
||||
|
||||
/** Set MFA_Rule_UU.
|
||||
@param MFA_Rule_UU MFA_Rule_UU */
|
||||
public void setMFA_Rule_UU (String MFA_Rule_UU)
|
||||
{
|
||||
set_Value (COLUMNNAME_MFA_Rule_UU, MFA_Rule_UU);
|
||||
}
|
||||
|
||||
/** Get MFA_Rule_UU.
|
||||
@return MFA_Rule_UU */
|
||||
public String getMFA_Rule_UU ()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_MFA_Rule_UU);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
package org.compiere.process;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.model.IMFAMechanism;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* IDEMPIERE-4782
|
||||
* @author Carlos Ruiz - globalqss - BX Service
|
||||
*/
|
||||
public class MFACompleteRegistration extends SvrProcess {
|
||||
/* MFA Registration */
|
||||
private int p_MFA_Registration_ID = 0;
|
||||
/* Validation Code */
|
||||
private String p_MFAValidationCode = null;
|
||||
/* Name */
|
||||
private String p_Name = null;
|
||||
/* Preferred */
|
||||
private boolean p_IsUserMFAPreferred = false;
|
||||
|
||||
@Override
|
||||
protected void prepare() {
|
||||
for (ProcessInfoParameter para : getParameter()) {
|
||||
String name = para.getParameterName();
|
||||
switch (name) {
|
||||
case "MFA_Registration_ID": p_MFA_Registration_ID = para.getParameterAsInt(); break;
|
||||
case "MFAValidationCode": p_MFAValidationCode = para.getParameterAsString(); break;
|
||||
case "Name": p_Name = para.getParameterAsString(); break;
|
||||
case "IsUserMFAPreferred": p_IsUserMFAPreferred = para.getParameterAsBoolean(); break;
|
||||
default:
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, "Custom Parameter: " + name + "=" + para.getInfo());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform process.
|
||||
* @return Message
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String doIt() throws Exception {
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.info("MFA_Registration_ID=" + p_MFA_Registration_ID
|
||||
+ ", MFAValidationCode=" + p_MFAValidationCode
|
||||
+ ", Name=" + p_Name
|
||||
+ ", IsUserMFAPreferred=" + p_IsUserMFAPreferred);
|
||||
|
||||
MMFARegistration reg = new MMFARegistration(getCtx(), p_MFA_Registration_ID, get_TrxName());
|
||||
if (reg.isValid())
|
||||
throw new AdempiereException(Msg.getMsg(getCtx(), "MFARegistrationAlreadyValid"));
|
||||
|
||||
if (Util.isEmpty(p_MFAValidationCode))
|
||||
throw new AdempiereException(Msg.getMsg(getCtx(), "MFACodeRequired"));
|
||||
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
if (reg.getExpiration() != null && now.after(reg.getExpiration())) {
|
||||
reg.setIsActive(false);
|
||||
reg.saveEx(null);
|
||||
throw new AdempiereException(Msg.getMsg(getCtx(), "MFARegistrationExpired"));
|
||||
}
|
||||
|
||||
MMFAMethod method = new MMFAMethod(getCtx(), reg.getMFA_Method_ID(), get_TrxName());
|
||||
IMFAMechanism mechanism = method.getMFAMechanism();
|
||||
|
||||
String msg = mechanism.complete(getCtx(), reg, p_MFAValidationCode, p_Name, p_IsUserMFAPreferred, get_TrxName());
|
||||
return msg;
|
||||
}
|
||||
|
||||
} // RegisterMFA
|
|
@ -0,0 +1,103 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.process;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.IMFAMechanism;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.util.AdempiereSystemError;
|
||||
import org.compiere.util.Msg;
|
||||
|
||||
/**
|
||||
* IDEMPIERE-4782
|
||||
* @author Carlos Ruiz - globalqss - BX Service
|
||||
*/
|
||||
public class MFARegister extends SvrProcess {
|
||||
|
||||
/* MFA Method */
|
||||
private int p_MFA_Method_ID = 0;
|
||||
/* Parameter Value */
|
||||
private String p_ParameterValue = null;
|
||||
|
||||
/* Return array from mechanism */
|
||||
protected Object[] retArray;
|
||||
|
||||
@Override
|
||||
protected void prepare() {
|
||||
for (ProcessInfoParameter para : getParameter()) {
|
||||
String name = para.getParameterName();
|
||||
switch (name) {
|
||||
case "MFA_Method_ID": p_MFA_Method_ID = para.getParameterAsInt(); break;
|
||||
case "ParameterValue": p_ParameterValue = para.getParameterAsString(); break;
|
||||
default:
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, "Custom Parameter: " + name + "=" + para.getInfo());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform process.
|
||||
* @return Message
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String doIt() throws Exception {
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.info("MFA_Method_ID=" + p_MFA_Method_ID
|
||||
+ ", ParameterValue=" + p_ParameterValue);
|
||||
|
||||
MMFAMethod method = new MMFAMethod(getCtx(), p_MFA_Method_ID, get_TrxName());
|
||||
IMFAMechanism mechanism = method.getMFAMechanism();
|
||||
|
||||
retArray = mechanism.register(getCtx(), method, p_ParameterValue, get_TrxName());
|
||||
if (retArray == null || retArray.length == 0 || ! (retArray[0] instanceof String) )
|
||||
throw new AdempiereSystemError("Wrong return from mechanism.validate");
|
||||
|
||||
if (processUI == null) {
|
||||
for (int i = 0; i < retArray.length; i++) {
|
||||
if (retArray[i] instanceof String) {
|
||||
String reti = (String) retArray[i];
|
||||
if (reti.startsWith("data:image/png;base64,"))
|
||||
addLog("<img src=\"" + reti + "\" width=\"180\" height=\"180\"/>"); // show QR code
|
||||
else
|
||||
addLog((String) reti);
|
||||
} else if (retArray[i] instanceof MMFARegistration) {
|
||||
MMFARegistration reg = (MMFARegistration) retArray[i];
|
||||
addLog(0, null, null, Msg.parseTranslation(getCtx(), "@Created@: @MFA_Registration_ID@"), MMFARegistration.Table_ID, reg.getMFA_Registration_ID());
|
||||
}
|
||||
}
|
||||
}
|
||||
// else -> when the process is driven by zkwebui it will show the MFARegisterForm next, no need to save the parameters
|
||||
|
||||
return "@OK@";
|
||||
}
|
||||
|
||||
} // MFARegister
|
|
@ -0,0 +1,96 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.process;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.MMFARegisteredDevice;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.util.Env;
|
||||
|
||||
/**
|
||||
* IDEMPIERE-4782
|
||||
* @author Carlos Ruiz - globalqss - BX Service
|
||||
*/
|
||||
public class MFARevokeDevice extends SvrProcess {
|
||||
|
||||
/* Revoke All */
|
||||
private Boolean p_MFARevokeAll = null;
|
||||
/* MFA Registered Device */
|
||||
private int p_MFA_RegisteredDevice_ID = 0;
|
||||
|
||||
@Override
|
||||
protected void prepare() {
|
||||
for (ProcessInfoParameter para : getParameter()) {
|
||||
String name = para.getParameterName();
|
||||
switch (name) {
|
||||
case "MFARevokeAll": p_MFARevokeAll = para.getParameterAsBoolean(); break;
|
||||
case "MFA_RegisteredDevice_ID": p_MFA_RegisteredDevice_ID = para.getParameterAsInt(); break;
|
||||
default:
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, "Custom Parameter: " + name + "=" + para.getInfo());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform process.
|
||||
* @return Message
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String doIt() throws Exception {
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.info("MFARevokeAll=" + p_MFARevokeAll
|
||||
+ ", MFA_RegisteredDevice_ID=" + p_MFA_RegisteredDevice_ID);
|
||||
|
||||
String where;
|
||||
List<Object> params = new ArrayList<Object>();
|
||||
params.add(Env.getAD_User_ID(getCtx()));
|
||||
if (p_MFARevokeAll) {
|
||||
where = "AD_User_ID=?";
|
||||
} else {
|
||||
where = "AD_User_ID=? AND (MFA_RegisteredDevice_ID=? OR Expiration<=SYSDATE)";
|
||||
params.add(p_MFA_RegisteredDevice_ID);
|
||||
}
|
||||
List<MMFARegisteredDevice> rds = new Query(getCtx(), MMFARegisteredDevice.Table_Name, where, get_TrxName())
|
||||
.setOnlyActiveRecords(true)
|
||||
.setClient_ID()
|
||||
.setParameters(params)
|
||||
.list();
|
||||
for (MMFARegisteredDevice rd : rds) {
|
||||
rd.setIsActive(false);
|
||||
rd.saveEx();
|
||||
}
|
||||
|
||||
return "@OK@";
|
||||
}
|
||||
|
||||
} // MFARevokeDevice
|
|
@ -0,0 +1,75 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
|
||||
package org.compiere.process;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.MMFARegistration;
|
||||
|
||||
/**
|
||||
* IDEMPIERE-4782
|
||||
* @author Carlos Ruiz - globalqss - BX Service
|
||||
*/
|
||||
public class MFAUnregister extends SvrProcess {
|
||||
|
||||
/* MFA Registration */
|
||||
private int p_MFA_Registration_ID = 0;
|
||||
|
||||
@Override
|
||||
protected void prepare() {
|
||||
for (ProcessInfoParameter para : getParameter()) {
|
||||
String name = para.getParameterName();
|
||||
switch (name) {
|
||||
case "MFA_Registration_ID": p_MFA_Registration_ID = para.getParameterAsInt(); break;
|
||||
default:
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.log(Level.INFO, "Custom Parameter: " + name + "=" + para.getInfo());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform process.
|
||||
* @return Message
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String doIt() throws Exception {
|
||||
if (log.isLoggable(Level.INFO))
|
||||
log.info("MFA_Registration_ID=" + p_MFA_Registration_ID);
|
||||
|
||||
MMFARegistration reg = new MMFARegistration(getCtx(), p_MFA_Registration_ID, get_TrxName());
|
||||
reg.setIsActive(false);
|
||||
reg.setMFAUnregisteredAt(new Timestamp(System.currentTimeMillis()));
|
||||
reg.saveEx();
|
||||
|
||||
return "@OK@";
|
||||
}
|
||||
|
||||
} // MFAUnregister
|
|
@ -38,6 +38,8 @@ import org.compiere.model.I_M_Warehouse;
|
|||
import org.compiere.model.MAcctSchema;
|
||||
import org.compiere.model.MClientInfo;
|
||||
import org.compiere.model.MCountry;
|
||||
import org.compiere.model.MMFARegisteredDevice;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MSystem;
|
||||
|
@ -1667,4 +1669,17 @@ public class Login
|
|||
return retValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if MFA is required taking into account the registerCookie and the IPAddress
|
||||
* @param registerCookie
|
||||
* @return
|
||||
*/
|
||||
public boolean isMFARequired(String registerCookie) {
|
||||
if (registerCookie != null && MMFARegisteredDevice.isValid(registerCookie))
|
||||
return false;
|
||||
if (MMFARegistration.userHasValidRegistration())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Login
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.idempiere.mfa;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.model.IMFAMechanism;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.model.MMailText;
|
||||
import org.compiere.model.MUser;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.util.EMail;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
public class EMailMechanism implements IMFAMechanism {
|
||||
|
||||
/**
|
||||
* Implement the registration mechanism for EMail Generate random code and
|
||||
* return in the array
|
||||
*
|
||||
* @param ctx
|
||||
* @param method
|
||||
* @param prm email
|
||||
* @param trxName
|
||||
* @return Object[] - first object is the String with the instructions to follow
|
||||
* second object is the registration generated
|
||||
*/
|
||||
@Override
|
||||
public Object[] register(Properties ctx, MMFAMethod method, String prm, String trxName) {
|
||||
if (Util.isEmpty(prm))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFAEMailRequired"));
|
||||
if (!EMail.validate(prm))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFAInvalidEMail"));
|
||||
if (method.getR_MailText_ID() <= 0)
|
||||
throw new AdempiereException("EMail method wrongly configured - requires mail template");
|
||||
|
||||
// just one time allowed per EMail
|
||||
if (MMFARegistration.alreadyExistsValid(method, prm))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFAMethodAlreadyRegistered"));
|
||||
|
||||
// Generate a random code and save it in MFA_Registration
|
||||
String otp = generateRandomString(6);
|
||||
|
||||
int expireMinutes = method.getExpireInMinutes();
|
||||
if (expireMinutes <= 0)
|
||||
expireMinutes = 15; // default to 15 minutes
|
||||
|
||||
MUser user = MUser.get(ctx);
|
||||
MMFARegistration reg = new MMFARegistration(ctx, 0, trxName);
|
||||
reg.setName(obfuscateEMail(prm));
|
||||
reg.setParameterValue(prm);
|
||||
reg.setMFA_Method_ID(method.getMFA_Method_ID());
|
||||
reg.setAD_User_ID(user.getAD_User_ID());
|
||||
reg.setMFASecret(otp);
|
||||
reg.setIsValid(false);
|
||||
reg.setIsUserMFAPreferred(false);
|
||||
reg.setExpiration(new Timestamp(System.currentTimeMillis() + (expireMinutes * 60000)));
|
||||
reg.saveEx();
|
||||
|
||||
// send the email
|
||||
MClient client = MClient.get(ctx);
|
||||
MMailText mt = new MMailText(ctx, method.getR_MailText_ID(), trxName);
|
||||
mt.setLanguage(Env.getContext(ctx, "#AD_Language"));
|
||||
mt.setUser(user.getAD_User_ID());
|
||||
mt.setPO(reg);
|
||||
String message = mt.getMailText(true);
|
||||
EMail email = client.createEMail(prm, mt.getMailHeader(), message, mt.isHtml());
|
||||
if (mt.isHtml())
|
||||
email.setMessageHTML(mt.getMailHeader(), message);
|
||||
else {
|
||||
email.setSubject(mt.getMailHeader());
|
||||
email.setMessageText(message);
|
||||
}
|
||||
if (!email.isValid() && !email.isValid(true))
|
||||
throw new AdempiereException("The EMail is not valid, check configuration");
|
||||
if (!EMail.SENT_OK.equals(email.send()))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFAProblemSendingEMail"));
|
||||
|
||||
// Invalidate any other previous pending registration with same method and email
|
||||
MMFARegistration.invalidatePreviousPending(method, prm, reg);
|
||||
|
||||
// Notify the user to check the email for the code
|
||||
Object[] ret = new Object[2];
|
||||
ret[0] = Msg.getMsg(Env.getCtx(), "MFAEMailCodeSent");
|
||||
ret[1] = reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a numeric random string of the specified length
|
||||
*
|
||||
* @param len
|
||||
* @return random String
|
||||
*/
|
||||
public static String generateRandomString(int len) {
|
||||
// String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // if upper alphanumeric is wanted
|
||||
String chars = "0123456789";
|
||||
Random rnd = new Random();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
sb.append(chars.charAt(rnd.nextInt(chars.length())));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete/Validate a previous EMail registration
|
||||
*
|
||||
* @param ctx
|
||||
* @param reg The registration object
|
||||
* @param p_MFAValidationCode The code to be validated
|
||||
* @param p_Name Optional - a name to assign the registration
|
||||
* @param get_TrxName
|
||||
* @return msg A message indicating success, errors throw exception
|
||||
*/
|
||||
@Override
|
||||
public String complete(Properties ctx, MMFARegistration reg, String code, String name, boolean preferred, String trxName) {
|
||||
boolean valid = code.equals(reg.getMFASecret());
|
||||
if (! valid) {
|
||||
reg.setLastFailure(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setFailedLoginCount(reg.getFailedLoginCount() + 1);
|
||||
try {
|
||||
PO.setCrossTenantSafe();
|
||||
reg.saveEx();
|
||||
} finally {
|
||||
PO.clearCrossTenantSafe();
|
||||
}
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFACodeInvalid"));
|
||||
}
|
||||
|
||||
// valid code
|
||||
reg.setMFALastSecret(code);
|
||||
reg.setLastSuccess(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setFailedLoginCount(0);
|
||||
reg.setIsValid(true);
|
||||
reg.setMFAValidatedAt(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setExpiration(null);
|
||||
if (!Util.isEmpty(name))
|
||||
reg.setName(name);
|
||||
if (preferred)
|
||||
reg.setIsUserMFAPreferred(true);
|
||||
try {
|
||||
PO.setCrossTenantSafe();
|
||||
reg.saveEx();
|
||||
} finally {
|
||||
PO.clearCrossTenantSafe();
|
||||
}
|
||||
|
||||
return Msg.getMsg(ctx, "MFARegistrationCompleted");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email with validation code
|
||||
* @param reg
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String generateValidationCode(MMFARegistration reg) {
|
||||
Properties ctx = reg.getCtx();
|
||||
MMFAMethod method = new MMFAMethod(ctx, reg.getMFA_Method_ID(), reg.get_TrxName());
|
||||
|
||||
// Generate a random code and save it in MFA_Registration
|
||||
String otp = generateRandomString(6);
|
||||
|
||||
int expireMinutes = method.getExpireInMinutes();
|
||||
if (expireMinutes <= 0)
|
||||
expireMinutes = 15; // default to 15 minutes
|
||||
|
||||
MUser user = MUser.get(reg.getCtx());
|
||||
reg.setMFASecret(otp);
|
||||
reg.setExpiration(new Timestamp(System.currentTimeMillis() + (expireMinutes * 60000)));
|
||||
try {
|
||||
PO.setCrossTenantSafe();
|
||||
reg.saveEx();
|
||||
} finally {
|
||||
PO.clearCrossTenantSafe();
|
||||
}
|
||||
|
||||
String mail_to = reg.getParameterValue();
|
||||
// send the email
|
||||
MClient client = MClient.get(ctx);
|
||||
MMailText mt = new MMailText(ctx, method.getR_MailText_ID(), reg.get_TrxName());
|
||||
mt.setLanguage(Env.getContext(ctx, "#AD_Language"));
|
||||
mt.setUser(user.getAD_User_ID());
|
||||
mt.setPO(reg);
|
||||
String message = mt.getMailText(true);
|
||||
EMail email = client.createEMail(mail_to, mt.getMailHeader(), message, mt.isHtml());
|
||||
if (mt.isHtml())
|
||||
email.setMessageHTML(mt.getMailHeader(), message);
|
||||
else {
|
||||
email.setSubject(mt.getMailHeader());
|
||||
email.setMessageText(message);
|
||||
}
|
||||
if (!email.isValid() && !email.isValid(true))
|
||||
throw new AdempiereException("The EMail is not valid, check configuration");
|
||||
if (!EMail.SENT_OK.equals(email.send()))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFAProblemSendingEMail"));
|
||||
|
||||
return Msg.getMsg(Env.getCtx(), "MFAEMailValidationCodeSent", new Object[] { obfuscateEMail(mail_to) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace internal characters in email with *
|
||||
* @param mail
|
||||
* @return
|
||||
*/
|
||||
private String obfuscateEMail(String mail) {
|
||||
StringBuilder mailObfuscated = new StringBuilder();
|
||||
boolean atFound = false;
|
||||
for (int idx = 0; idx < mail.length(); idx++) {
|
||||
char chr = mail.charAt(idx);
|
||||
if (chr == '@') {
|
||||
atFound = true;
|
||||
} else if ((!atFound && idx > 1) || (atFound && idx < mail.length() - 4)) {
|
||||
chr = '*';
|
||||
}
|
||||
mailObfuscated.append(chr);
|
||||
}
|
||||
return mailObfuscated.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a code
|
||||
* @param reg
|
||||
* @param code
|
||||
* @param setPreferred
|
||||
* @return message on error, null when OK
|
||||
*/
|
||||
@Override
|
||||
public String validateCode(MMFARegistration reg, String code, boolean setPreferred) {
|
||||
Properties ctx = reg.getCtx();
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
if (reg.getExpiration() != null && now.after(reg.getExpiration()))
|
||||
return Msg.getMsg(ctx, "MFARegistrationExpired");
|
||||
if (code.equals(reg.getMFALastSecret()))
|
||||
return Msg.getMsg(ctx, "MFACodeAlreadyConsumed");
|
||||
|
||||
boolean valid = code.equals(reg.getMFASecret());
|
||||
if (! valid) {
|
||||
reg.setLastFailure(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setFailedLoginCount(reg.getFailedLoginCount() + 1);
|
||||
reg.saveEx();
|
||||
return Msg.getMsg(ctx, "MFACodeInvalid");
|
||||
}
|
||||
|
||||
reg.setMFALastSecret(code);
|
||||
reg.setLastSuccess(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setFailedLoginCount(0);
|
||||
if (setPreferred)
|
||||
reg.setIsUserMFAPreferred(true);
|
||||
try {
|
||||
PO.setCrossTenantSafe();
|
||||
reg.saveEx();
|
||||
} finally {
|
||||
PO.clearCrossTenantSafe();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.idempiere.mfa;
|
||||
|
||||
import static dev.samstevens.totp.util.Utils.getDataUriForImage;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.model.IMFAMechanism;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MUser;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
import dev.samstevens.totp.code.CodeGenerator;
|
||||
import dev.samstevens.totp.code.DefaultCodeGenerator;
|
||||
import dev.samstevens.totp.code.DefaultCodeVerifier;
|
||||
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||
import dev.samstevens.totp.qr.QrData;
|
||||
import dev.samstevens.totp.qr.QrGenerator;
|
||||
import dev.samstevens.totp.qr.ZxingPngQrGenerator;
|
||||
import dev.samstevens.totp.secret.DefaultSecretGenerator;
|
||||
import dev.samstevens.totp.secret.SecretGenerator;
|
||||
import dev.samstevens.totp.time.NtpTimeProvider;
|
||||
import dev.samstevens.totp.time.SystemTimeProvider;
|
||||
import dev.samstevens.totp.time.TimeProvider;
|
||||
|
||||
public class TOTPMechanism implements IMFAMechanism {
|
||||
|
||||
/**
|
||||
* Implement the registration mechanism for TOTP
|
||||
* Generate the secret and the qrcode and return in the array
|
||||
* @param ctx
|
||||
* @param method
|
||||
* @param prm optional - assigned name from the user
|
||||
* @param trxName
|
||||
* @return Object[] - first object is the String with the instructions to follow
|
||||
* second object is the registration generated
|
||||
* third message qrcode
|
||||
* fourth qrcode
|
||||
* fifth message secret
|
||||
* sixth secret
|
||||
*/
|
||||
@Override
|
||||
public Object[] register(Properties ctx, MMFAMethod method, String prm, String trxName) {
|
||||
if (Util.isEmpty(method.getMFAIssuer()))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFATOTPIssuerRequired"));
|
||||
|
||||
if (MMFARegistration.alreadyExistsValid(method, prm))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFAMethodAlreadyRegistered"));
|
||||
|
||||
MUser user = MUser.get(ctx);
|
||||
String label;
|
||||
boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false);
|
||||
if (email_login)
|
||||
label = user.getEMail();
|
||||
else
|
||||
label = user.getName();
|
||||
|
||||
SecretGenerator secretGenerator = new DefaultSecretGenerator();
|
||||
String secret = secretGenerator.generate();
|
||||
|
||||
QrData data = new QrData.Builder()
|
||||
.label(label)
|
||||
.secret(secret)
|
||||
.issuer(method.getMFAIssuer())
|
||||
.build();
|
||||
|
||||
QrGenerator generator = new ZxingPngQrGenerator();
|
||||
byte[] imageData;
|
||||
try {
|
||||
imageData = generator.generate(data);
|
||||
} catch (QrGenerationException e) {
|
||||
throw new AdempiereException(Msg.getMsg(Env.getCtx(), "MFATOTPErrorGeneratingQR"), e);
|
||||
}
|
||||
String mimeType = generator.getImageMimeType();
|
||||
String dataUri = getDataUriForImage(imageData, mimeType);
|
||||
|
||||
int expireMinutes = method.getExpireInMinutes();
|
||||
|
||||
MMFARegistration reg = new MMFARegistration(ctx, 0, trxName);
|
||||
if (! Util.isEmpty(prm)) {
|
||||
reg.setName(prm);
|
||||
reg.setParameterValue(prm);
|
||||
} else {
|
||||
reg.setName(label);
|
||||
}
|
||||
reg.setMFA_Method_ID(method.getMFA_Method_ID());
|
||||
reg.setAD_User_ID(user.getAD_User_ID());
|
||||
reg.setMFASecret(secret);
|
||||
reg.setIsValid(false);
|
||||
reg.setIsUserMFAPreferred(false);
|
||||
if (expireMinutes > 0)
|
||||
reg.setExpiration(new Timestamp(System.currentTimeMillis() + (expireMinutes*60000)));
|
||||
reg.saveEx();
|
||||
|
||||
// Invalidate any other previous pending registration with same method
|
||||
MMFARegistration.invalidatePreviousPending(method, prm, reg);
|
||||
|
||||
// Notify the user that TOTP mechanism was registered and follow next step
|
||||
Object[] ret = new Object[6];
|
||||
ret[0] = Msg.getMsg(Env.getCtx(), "MFATOTPRegistered");
|
||||
ret[1] = reg;
|
||||
ret[2] = Msg.getMsg(Env.getCtx(), "MFATOTPImage");
|
||||
ret[3] = dataUri;
|
||||
ret[4] = Msg.getMsg(Env.getCtx(), "MFATOTPSecret");
|
||||
ret[5] = secret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete/Validate a previous TOTP registration
|
||||
* @param ctx
|
||||
* @param reg The registration object
|
||||
* @param p_MFAValidationCode The code to be validated
|
||||
* @param p_Name Optional - a name to assign the registration
|
||||
* @param trxName
|
||||
* @return msg A message indicating success, errors throw exception
|
||||
*/
|
||||
@Override
|
||||
public String complete(Properties ctx, MMFARegistration reg, String code, String name, boolean preferred, String trxName) {
|
||||
if (! isValidCode(ctx, reg, code, trxName))
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFACodeInvalid"));
|
||||
|
||||
// valid code
|
||||
reg.setIsValid(true);
|
||||
reg.setMFAValidatedAt(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setExpiration(null);
|
||||
if (!Util.isEmpty(name))
|
||||
reg.setName(name);
|
||||
if (preferred)
|
||||
reg.setIsUserMFAPreferred(true);
|
||||
reg.saveEx();
|
||||
|
||||
return Msg.getMsg(ctx, "MFARegistrationCompleted");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reg
|
||||
* @param code
|
||||
* @param trxName
|
||||
* @return
|
||||
*/
|
||||
private boolean isValidCode(Properties ctx, MMFARegistration reg, String code, String trxName) {
|
||||
MMFAMethod method = new MMFAMethod(ctx, reg.getMFA_Method_ID(), trxName);
|
||||
TimeProvider timeProvider;
|
||||
if (MMFAMethod.MFATIMEPROVIDER_Ntp.equals(method.getMFATimeProvider())) {
|
||||
String ntpServer = method.getMFATimeServer();
|
||||
if (Util.isEmpty(ntpServer))
|
||||
ntpServer = "pool.ntp.org";
|
||||
int timeout = MSysConfig.getIntValue(MSysConfig.MFA_NTP_TIMEOUT_IN_MILLISECONDS, 5000);
|
||||
try {
|
||||
timeProvider = new NtpTimeProvider(ntpServer, timeout);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new AdempiereException(Msg.getMsg(ctx, "MFANTPServerError") + e.getLocalizedMessage(), e);
|
||||
}
|
||||
} else { // default to System
|
||||
timeProvider = new SystemTimeProvider();
|
||||
}
|
||||
CodeGenerator codeGenerator = new DefaultCodeGenerator();
|
||||
DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);
|
||||
if (method.getMFAAllowedTimeDiscrepancy() > 0) {
|
||||
// allow codes valid for the time periods configured before/after to pass as valid (default is 1)
|
||||
verifier.setAllowedTimePeriodDiscrepancy(method.getMFAAllowedTimeDiscrepancy());
|
||||
}
|
||||
|
||||
boolean valid = verifier.isValidCode(reg.getMFASecret(), code);
|
||||
if (valid) {
|
||||
reg.setMFALastSecret(code);
|
||||
reg.setLastSuccess(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setFailedLoginCount(0);
|
||||
} else {
|
||||
reg.setLastFailure(new Timestamp(System.currentTimeMillis()));
|
||||
reg.setFailedLoginCount(reg.getFailedLoginCount() + 1);
|
||||
}
|
||||
try {
|
||||
PO.setCrossTenantSafe();
|
||||
reg.saveEx();
|
||||
} finally {
|
||||
PO.clearCrossTenantSafe();
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a validation code - do nothing for TOTP
|
||||
* @param reg
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String generateValidationCode(MMFARegistration reg) {
|
||||
return Msg.getMsg(Env.getCtx(), "MFATOTPEnterValidationCode");
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a code
|
||||
* @param reg
|
||||
* @param code
|
||||
* @param setPreferred
|
||||
* @return message on error, null when OK
|
||||
*/
|
||||
@Override
|
||||
public String validateCode(MMFARegistration reg, String code, boolean setPreferred) {
|
||||
Properties ctx = reg.getCtx();
|
||||
if (code.equals(reg.getMFALastSecret()))
|
||||
return Msg.getMsg(ctx, "MFACodeAlreadyConsumed");
|
||||
|
||||
if (! isValidCode(ctx, reg, code, reg.get_TrxName()))
|
||||
return Msg.getMsg(ctx, "MFACodeInvalid");
|
||||
|
||||
if (setPreferred) {
|
||||
reg.setIsUserMFAPreferred(true);
|
||||
try {
|
||||
PO.setCrossTenantSafe();
|
||||
reg.saveEx();
|
||||
} finally {
|
||||
PO.clearCrossTenantSafe();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -97,6 +97,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -94,6 +94,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -94,6 +94,8 @@
|
|||
<setEntry value="slf4j.api@default:default"/>
|
||||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -370,6 +370,8 @@
|
|||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="stax2-api@default:default"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -371,6 +371,8 @@
|
|||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="stax2-api@default:default"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
|
@ -79,7 +79,9 @@ osgi.bundles=org.eclipse.equinox.ds@1:start,\
|
|||
org.apache.geronimo.specs.geronimo-j2ee-management_1.1_spec,\
|
||||
jakarta.xml.bind-api,\
|
||||
org.eclipse.osgi@start,\
|
||||
org.dom4j
|
||||
org.dom4j,\
|
||||
wrapped.com.google.zxing.javase,\
|
||||
wrapped.dev.samstevens.totp.totp
|
||||
osgi.framework.extensions=
|
||||
osgi.bundles.defaultStartLevel=4
|
||||
osgi.compatibility.bootdelegation=true
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.adempiere.webui.process.MFARegisterParameterListener">
|
||||
<implementation class="org.adempiere.webui.process.MFARegisterParameterListener"/>
|
||||
<property name="ProcessClass" type="String" value="org.compiere.process.MFARegister"/>
|
||||
<property name="ColumnName" type="String" value="MFA_Method_ID"/>
|
||||
<service>
|
||||
<provide interface="org.adempiere.webui.apps.IProcessParameterListener"/>
|
||||
</service>
|
||||
</scr:component>
|
|
@ -0,0 +1,250 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
|
||||
package org.adempiere.webui.apps.form;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import org.adempiere.webui.component.Checkbox;
|
||||
import org.adempiere.webui.component.Column;
|
||||
import org.adempiere.webui.component.Columns;
|
||||
import org.adempiere.webui.component.ConfirmPanel;
|
||||
import org.adempiere.webui.component.GridFactory;
|
||||
import org.adempiere.webui.component.Label;
|
||||
import org.adempiere.webui.component.Row;
|
||||
import org.adempiere.webui.component.Rows;
|
||||
import org.adempiere.webui.component.Textbox;
|
||||
import org.adempiere.webui.panel.ADForm;
|
||||
import org.compiere.model.IMFAMechanism;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
import org.zkoss.zk.ui.WrongValueException;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Html;
|
||||
import org.zkoss.zul.Separator;
|
||||
import org.zkoss.zul.Space;
|
||||
|
||||
/**
|
||||
* IDEMPIERE-4782
|
||||
* @author Carlos Ruiz - globalqss - BX Service
|
||||
*/
|
||||
public class MFARegisterForm extends ADForm {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 6186035815377577281L;
|
||||
|
||||
/* A label to show the messages to user */
|
||||
private Html msgInstructions;
|
||||
|
||||
/* A label to show the additional messages to user */
|
||||
private Html msgAdditional;
|
||||
|
||||
/* A box to receive the validation code */
|
||||
private Label codeLabel;
|
||||
private Textbox codeBox;
|
||||
|
||||
/* A box to receive optionally a name */
|
||||
private Label nameLabel;
|
||||
private Textbox nameBox;
|
||||
|
||||
/* A checkbox to set registration as preferred */
|
||||
private Checkbox prefBox;
|
||||
|
||||
/* The confirm panel to close the window */
|
||||
private ConfirmPanel confirmPanel;
|
||||
|
||||
/* The process instance opening this form */
|
||||
@SuppressWarnings("unused")
|
||||
private int pInstanceId;
|
||||
|
||||
private MMFARegistration registration = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public MFARegisterForm() {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.adempiere.webui.panel.ADForm#initForm()
|
||||
*/
|
||||
@Override
|
||||
protected void initForm() {
|
||||
setClosable(true);
|
||||
setSizable(true);
|
||||
|
||||
Grid grid = GridFactory.newGridLayout();
|
||||
grid.setHeight("100%");
|
||||
grid.setWidth("100%");
|
||||
appendChild(grid);
|
||||
Columns columns = new Columns();
|
||||
grid.appendChild(columns);
|
||||
Column column = new Column();
|
||||
column.setWidth("5%");
|
||||
columns.appendChild(column);
|
||||
column = new Column();
|
||||
column.setWidth("30%");
|
||||
columns.appendChild(column);
|
||||
column = new Column();
|
||||
column.setWidth("60%");
|
||||
columns.appendChild(column);
|
||||
column = new Column();
|
||||
column.setWidth("10%");
|
||||
columns.appendChild(column);
|
||||
|
||||
Rows rows = new Rows();
|
||||
grid.appendChild(rows);
|
||||
|
||||
Row row = rows.newRow();
|
||||
row = rows.newRow();
|
||||
msgInstructions = new Html();
|
||||
row.appendCellChild(msgInstructions, 4);
|
||||
msgInstructions.setHflex("1");
|
||||
|
||||
row = rows.newRow();
|
||||
msgAdditional = new Html();
|
||||
row.appendCellChild(msgAdditional, 4);
|
||||
msgAdditional.setHflex("1");
|
||||
|
||||
row = rows.newRow();
|
||||
codeLabel = new Label(Msg.getElement(Env.getCtx(), "MFAValidationCode"));
|
||||
row.appendCellChild(codeLabel, 2);
|
||||
codeBox = new Textbox();
|
||||
row.appendCellChild(codeBox, 2);
|
||||
|
||||
row = rows.newRow();
|
||||
nameLabel = new Label(Msg.getElement(Env.getCtx(), "Name"));
|
||||
row.appendCellChild(nameLabel, 2);
|
||||
nameBox = new Textbox();
|
||||
row.appendCellChild(nameBox, 2);
|
||||
|
||||
row = rows.newRow();
|
||||
row.appendCellChild(new Separator(), 2);
|
||||
prefBox = new Checkbox();
|
||||
prefBox.setLabel(Msg.getElement(Env.getCtx(), "IsUserMFAPreferred"));
|
||||
row.appendCellChild(prefBox, 2);
|
||||
|
||||
row = rows.newRow();
|
||||
confirmPanel = new ConfirmPanel(true);
|
||||
row.appendCellChild(new Space());
|
||||
row.appendCellChild(confirmPanel, 3);
|
||||
confirmPanel.addActionListener(Events.ON_CLICK, evt -> onConfirmPanelAction(evt));
|
||||
|
||||
//setHeight("600px");
|
||||
setHeight(null);
|
||||
setWidth("350px");
|
||||
setVflex("min");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Window Mode Highlighted
|
||||
*/
|
||||
@Override
|
||||
public Mode getWindowMode() {
|
||||
return Mode.HIGHLIGHTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm panel to process OK/Cancel buttons
|
||||
* @param evt
|
||||
*/
|
||||
private void onConfirmPanelAction(Event evt) {
|
||||
if (evt.getTarget() == confirmPanel.getButton(ConfirmPanel.A_CANCEL)) {
|
||||
this.detach();
|
||||
} else if (evt.getTarget() == confirmPanel.getButton(ConfirmPanel.A_OK)) {
|
||||
if (codeBox.isDisabled())
|
||||
this.detach();
|
||||
|
||||
if (Util.isEmpty(codeBox.getValue()))
|
||||
throw new WrongValueException(codeBox, Msg.getMsg(Env.getCtx(), "MFACodeRequired"));
|
||||
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
if (registration.getExpiration() != null && now.after(registration.getExpiration()))
|
||||
throw new WrongValueException(codeBox, Msg.getMsg(Env.getCtx(), "MFARegistrationExpired"));
|
||||
|
||||
MMFAMethod method = new MMFAMethod(Env.getCtx(), registration.getMFA_Method_ID(), registration.get_TrxName());
|
||||
IMFAMechanism mechanism = method.getMFAMechanism();
|
||||
|
||||
String msg;
|
||||
try {
|
||||
msg = mechanism.complete(Env.getCtx(), registration, codeBox.getValue(), nameBox.getValue(), prefBox.isChecked(), registration.get_TrxName());
|
||||
} catch (Exception e) {
|
||||
String err;
|
||||
if (! Util.isEmpty(e.getLocalizedMessage()))
|
||||
err = e.getLocalizedMessage();
|
||||
else
|
||||
err = Msg.getMsg(Env.getCtx(), "Error") + " = " + e.toString();
|
||||
throw new WrongValueException(codeBox, err);
|
||||
}
|
||||
codeBox.setDisabled(true);
|
||||
nameBox.setDisabled(true);
|
||||
prefBox.setDisabled(true);
|
||||
msgInstructions.setContent(msg);
|
||||
msgAdditional.setContent(null);
|
||||
|
||||
confirmPanel.getButton(ConfirmPanel.A_CANCEL).setDisabled(true);
|
||||
confirmPanel.getButton(ConfirmPanel.A_CANCEL).setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param retArray
|
||||
* @param pInstanceId
|
||||
*/
|
||||
public void completeRegistration(Object[] retArray, int pInstanceId) {
|
||||
this.pInstanceId = pInstanceId;
|
||||
|
||||
String instructions = retArray[0].toString();
|
||||
StringBuilder additionalInstructions = new StringBuilder();
|
||||
for (int i = 1; i < retArray.length; i++) {
|
||||
if (retArray[i] instanceof String) {
|
||||
if (additionalInstructions.length() > 0)
|
||||
additionalInstructions.append("<br>");
|
||||
String reti = (String) retArray[i];
|
||||
if (reti.startsWith("data:image/png;base64,"))
|
||||
additionalInstructions.append("<img src=\"" + reti.toString() + "\" width=\"180\" height=\"180\"/>"); // show QR code
|
||||
else
|
||||
additionalInstructions.append(reti.toString());
|
||||
} else if (retArray[i] instanceof MMFARegistration) {
|
||||
registration = (MMFARegistration) retArray[i];
|
||||
}
|
||||
}
|
||||
msgInstructions.setContent(instructions);
|
||||
msgAdditional.setContent(additionalInstructions.toString());
|
||||
nameBox.setValue(registration.getName());
|
||||
registration.set_TrxName(null); // this is post-process, the transaction from the process was already closed
|
||||
}
|
||||
|
||||
}
|
|
@ -806,7 +806,9 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
|||
sideController.onLogOut();
|
||||
sideController = null;
|
||||
}
|
||||
if (layout != null) {
|
||||
layout.detach();
|
||||
}
|
||||
layout = null;
|
||||
pnlHead = null;
|
||||
max = null;
|
||||
|
|
|
@ -126,6 +126,9 @@ public class LoginPanel extends Window implements EventListener<Event>
|
|||
protected boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false);
|
||||
protected String validLstLanguage = null;
|
||||
|
||||
/* Number of failures to calculate an incremental delay on every trial */
|
||||
private int failures = 0;
|
||||
|
||||
public LoginPanel(Properties ctx, LoginWindow loginWindow)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
|
@ -592,6 +595,11 @@ public class LoginPanel extends Window implements EventListener<Event>
|
|||
}
|
||||
logAuthFailure.log(x_Forward_IP, "/webui", userId, loginErrMsg);
|
||||
|
||||
// Incremental delay to avoid brute-force attack on testing codes
|
||||
try {
|
||||
Thread.sleep(failures * 2000);
|
||||
} catch (InterruptedException e) {}
|
||||
failures++;
|
||||
Clients.clearBusy();
|
||||
throw new WrongValueException(loginErrMsg);
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ package org.adempiere.webui.panel;
|
|||
import java.sql.Timestamp;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.adempiere.util.Callback;
|
||||
import org.adempiere.webui.AdempiereIdGenerator;
|
||||
import org.adempiere.webui.LayoutUtils;
|
||||
|
@ -52,15 +50,12 @@ import org.compiere.util.KeyNamePair;
|
|||
import org.compiere.util.Language;
|
||||
import org.compiere.util.Login;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.TimeUtil;
|
||||
import org.compiere.util.Util;
|
||||
import org.zkoss.zhtml.Table;
|
||||
import org.zkoss.zhtml.Td;
|
||||
import org.zkoss.zhtml.Tr;
|
||||
import org.zkoss.zk.au.out.AuFocus;
|
||||
import org.zkoss.zk.au.out.AuScript;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
import org.zkoss.zk.ui.Session;
|
||||
import org.zkoss.zk.ui.WrongValueException;
|
||||
import org.zkoss.zk.ui.event.Deferrable;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
|
@ -85,7 +80,7 @@ public class RolePanel extends Window implements EventListener<Event>, Deferrabl
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4763398859555693370L;
|
||||
private static final long serialVersionUID = -618446343598384819L;
|
||||
|
||||
protected LoginWindow wndLogin;
|
||||
protected Login login;
|
||||
|
@ -638,17 +633,6 @@ public class RolePanel extends Window implements EventListener<Event>, Deferrabl
|
|||
Timestamp date = (Timestamp)lstDate.getValue();
|
||||
|
||||
String msg = login.loadPreferences(orgKNPair, warehouseKNPair, date, null);
|
||||
if (Util.isEmpty(msg))
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
msg = login.validateLogin(orgKNPair);
|
||||
}
|
||||
if (! Util.isEmpty(msg))
|
||||
{
|
||||
Env.getCtx().clear();
|
||||
|
@ -661,38 +645,29 @@ public class RolePanel extends Window implements EventListener<Event>, Deferrabl
|
|||
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))
|
||||
FDialog.warn(0, null, "", Msg.getMsg(Env.getCtx(), "YourPasswordWillExpireInDays", new Object[] {TimeUtil.getDaysBetween(now, limit)}));
|
||||
}
|
||||
}
|
||||
|
||||
wndLogin.loginCompleted();
|
||||
|
||||
// Elaine 2009/02/06 save preference to AD_Preference
|
||||
UserPreference userPreference = SessionManager.getSessionApplication().getUserPreference();
|
||||
userPreference.setProperty(UserPreference.P_LANGUAGE, Env.getContext(m_ctx, UserPreference.LANGUAGE_NAME));
|
||||
userPreference.setProperty(UserPreference.P_ROLE, (String) lstItemRole.getValue());
|
||||
userPreference.setProperty(UserPreference.P_CLIENT, (String) lstItemClient.getValue());
|
||||
userPreference.setProperty(UserPreference.P_ORG, (String) lstItemOrg.getValue());
|
||||
userPreference.setProperty(UserPreference.P_WAREHOUSE, lstItemWarehouse != null ? (String) lstItemWarehouse.getValue() : "0");
|
||||
userPreference.setProperty(UserPreference.P_WAREHOUSE,
|
||||
lstItemWarehouse != null ? (String) lstItemWarehouse.getValue() : "0");
|
||||
userPreference.savePreference();
|
||||
|
||||
// force reload of default role when more than 1 client
|
||||
if (lstClient.getChildren().size() > 1)
|
||||
MRole.getDefault(m_ctx, true);
|
||||
//
|
||||
|
||||
wndLogin.validateMFA(orgKNPair);
|
||||
}
|
||||
|
||||
public boolean isDeferrable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean show() {
|
||||
return m_show;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,439 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz (sponsored by FH) *
|
||||
**********************************************************************/
|
||||
|
||||
package org.adempiere.webui.panel;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
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;
|
||||
import org.adempiere.webui.component.ComboItem;
|
||||
import org.adempiere.webui.component.Combobox;
|
||||
import org.adempiere.webui.component.ConfirmPanel;
|
||||
import org.adempiere.webui.component.Label;
|
||||
import org.adempiere.webui.component.Textbox;
|
||||
import org.adempiere.webui.component.Window;
|
||||
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.FDialog;
|
||||
import org.adempiere.webui.window.LoginWindow;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.model.MMFARegisteredDevice;
|
||||
import org.compiere.model.MMFARegistration;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MUser;
|
||||
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.TimeUtil;
|
||||
import org.compiere.util.Util;
|
||||
import org.zkoss.zhtml.Div;
|
||||
import org.zkoss.zhtml.Table;
|
||||
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;
|
||||
|
||||
public class ValidateMFAPanel extends Window implements EventListener<Event> {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5521412080450156787L;
|
||||
|
||||
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;
|
||||
protected Label lblValidationCode;
|
||||
protected Textbox txtValidationCode;
|
||||
protected Checkbox chkSetPreferred;
|
||||
protected Checkbox chkRegisterDevice = null;
|
||||
|
||||
private KeyNamePair m_orgKNPair;
|
||||
|
||||
/* Push the first OK automatically - when the first record is TOTP */
|
||||
private boolean m_autoCall = false;
|
||||
|
||||
private static LogAuthFailure logAuthFailure = new LogAuthFailure();
|
||||
|
||||
/* Number of failures to calculate an incremental delay on every trial */
|
||||
private int failures = 0;
|
||||
|
||||
public ValidateMFAPanel(Properties ctx, LoginWindow loginWindow, KeyNamePair orgKNPair) {
|
||||
this.wndLogin = loginWindow;
|
||||
m_ctx = ctx;
|
||||
this.m_orgKNPair = orgKNPair;
|
||||
this.component = this;
|
||||
|
||||
String cookieName = Env.getAD_User_ID(m_ctx) + "|" + Env.getAD_Client_ID(m_ctx);
|
||||
String registerCookie = getCookie(cookieName);
|
||||
login = new Login(ctx);
|
||||
if (login.isMFARequired(registerCookie)) {
|
||||
initComponents();
|
||||
init();
|
||||
this.setId("validateMFAPanel");
|
||||
this.setSclass("login-box");
|
||||
|
||||
AuFocus auf = new AuFocus(lstMFAMechanism);
|
||||
Clients.response(auf);
|
||||
|
||||
if (m_autoCall) {
|
||||
validateMFAComplete(true);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (logger.isLoggable(Level.INFO)) logger.info("MFA not required");
|
||||
validateMFAComplete(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void init() {
|
||||
Div div = new Div();
|
||||
div.setSclass(ITheme.LOGIN_BOX_HEADER_CLASS);
|
||||
Label label = new Label(Msg.getMsg(m_ctx, "MFALoginValidationHeader"));
|
||||
label.setSclass(ITheme.LOGIN_BOX_HEADER_TXT_CLASS);
|
||||
div.appendChild(label);
|
||||
this.appendChild(div);
|
||||
|
||||
Table table = new Table();
|
||||
table.setId("grdMFAValidate");
|
||||
table.setDynamicProperty("cellpadding", "0");
|
||||
table.setDynamicProperty("cellspacing", "5");
|
||||
table.setSclass(ITheme.LOGIN_BOX_BODY_CLASS);
|
||||
|
||||
this.appendChild(table);
|
||||
|
||||
Tr tr = new Tr();
|
||||
table.appendChild(tr);
|
||||
Td td = new Td();
|
||||
td.setSclass(ITheme.LOGIN_BOX_HEADER_LOGO_CLASS);
|
||||
tr.appendChild(td);
|
||||
td.setDynamicProperty("colspan", "2");
|
||||
Image image = new Image();
|
||||
image.setSrc(ThemeManager.getLargeLogo());
|
||||
td.appendChild(image);
|
||||
|
||||
tr = new Tr();
|
||||
tr.setId("rowMFAMechanism");
|
||||
table.appendChild(tr);
|
||||
td = new Td();
|
||||
tr.appendChild(td);
|
||||
td.setSclass(ITheme.LOGIN_LABEL_CLASS);
|
||||
td.appendChild(lblMFAMechanism);
|
||||
td = new Td();
|
||||
td.setSclass(ITheme.LOGIN_FIELD_CLASS);
|
||||
tr.appendChild(td);
|
||||
td.appendChild(lstMFAMechanism);
|
||||
|
||||
tr = new Tr();
|
||||
tr.setId("rowMFAMsg");
|
||||
table.appendChild(tr);
|
||||
td = new Td();
|
||||
tr.appendChild(td);
|
||||
td.setSclass(ITheme.LOGIN_LABEL_CLASS);
|
||||
td.appendChild(new Label(""));
|
||||
td = new Td();
|
||||
tr.appendChild(td);
|
||||
td.setSclass(ITheme.LOGIN_FIELD_CLASS);
|
||||
td.appendChild(lblMFAMsg);
|
||||
|
||||
tr = new Tr();
|
||||
tr.setId("rowValidationCode");
|
||||
table.appendChild(tr);
|
||||
td = new Td();
|
||||
tr.appendChild(td);
|
||||
td.setSclass(ITheme.LOGIN_LABEL_CLASS);
|
||||
td.appendChild(lblValidationCode);
|
||||
td = new Td();
|
||||
td.setSclass(ITheme.LOGIN_FIELD_CLASS);
|
||||
tr.appendChild(td);
|
||||
td.appendChild(txtValidationCode);
|
||||
|
||||
tr = new Tr();
|
||||
tr.setId("rowSetPreferred");
|
||||
table.appendChild(tr);
|
||||
td = new Td();
|
||||
tr.appendChild(td);
|
||||
td.setSclass(ITheme.LOGIN_LABEL_CLASS);
|
||||
td.appendChild(new Label(""));
|
||||
td = new Td();
|
||||
td.setSclass(ITheme.LOGIN_FIELD_CLASS);
|
||||
tr.appendChild(td);
|
||||
td.appendChild(chkSetPreferred);
|
||||
|
||||
tr = new Tr();
|
||||
tr.setId("rowRegisterDevice");
|
||||
table.appendChild(tr);
|
||||
td = new Td();
|
||||
tr.appendChild(td);
|
||||
td.setSclass(ITheme.LOGIN_LABEL_CLASS);
|
||||
td.appendChild(new Label(""));
|
||||
td = new Td();
|
||||
td.setSclass(ITheme.LOGIN_FIELD_CLASS);
|
||||
tr.appendChild(td);
|
||||
td.appendChild(chkRegisterDevice);
|
||||
|
||||
div = new Div();
|
||||
div.setSclass(ITheme.LOGIN_BOX_FOOTER_CLASS);
|
||||
ConfirmPanel pnlButtons = new ConfirmPanel(true);
|
||||
pnlButtons.addActionListener(this);
|
||||
LayoutUtils.addSclass(ITheme.LOGIN_BOX_FOOTER_PANEL_CLASS, pnlButtons);
|
||||
ZKUpdateUtil.setWidth(pnlButtons, null);
|
||||
pnlButtons.getButton(ConfirmPanel.A_OK).setSclass(ITheme.LOGIN_BUTTON_CLASS);
|
||||
pnlButtons.getButton(ConfirmPanel.A_CANCEL).setSclass(ITheme.LOGIN_BUTTON_CLASS);
|
||||
div.appendChild(pnlButtons);
|
||||
this.appendChild(div);
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
lblMFAMechanism = new Label();
|
||||
lblMFAMechanism.setId("lblMFAMechanism");
|
||||
lblMFAMechanism.setValue(Msg.getMsg(m_ctx, "MFALoginMechanism"));
|
||||
|
||||
lblValidationCode = new Label();
|
||||
lblValidationCode.setId("lblValidationCode");
|
||||
lblValidationCode.setValue(Msg.getMsg(m_ctx, "MFALoginValidationCode"));
|
||||
|
||||
lblMFAMsg = new Label();
|
||||
lblMFAMsg.setId("lblMFAMsg");
|
||||
lblMFAMsg.setValue(Msg.getMsg(m_ctx, "MFALoginMessage"));
|
||||
|
||||
lstMFAMechanism = new Combobox();
|
||||
lstMFAMechanism.setAutocomplete(true);
|
||||
lstMFAMechanism.setAutodrop(true);
|
||||
lstMFAMechanism.setId("lstMFAMechanism");
|
||||
boolean first = true;
|
||||
for (MMFARegistration reg : MMFARegistration.getValidRegistrationsFromUser()) {
|
||||
MMFAMethod method = new MMFAMethod(m_ctx, reg.getMFA_Method_ID(), reg.get_TrxName());
|
||||
if (first) {
|
||||
first = false;
|
||||
if (MMFAMethod.METHOD_Time_BasedOne_TimePassword.equals(method.getMethod())) {
|
||||
m_autoCall = true;
|
||||
}
|
||||
}
|
||||
ComboItem ci = new ComboItem(reg.getName() + " - " + method.getMethod(), reg.getMFA_Registration_ID());
|
||||
String id = AdempiereIdGenerator.escapeId(ci.getLabel());
|
||||
if (lstMFAMechanism.getFellowIfAny(id) == null)
|
||||
ci.setId(id);
|
||||
lstMFAMechanism.appendChild(ci);
|
||||
}
|
||||
lstMFAMechanism.setSelectedIndex(0);
|
||||
ZKUpdateUtil.setWidth(lstMFAMechanism, "220px");
|
||||
|
||||
chkSetPreferred = new Checkbox(Msg.getMsg(m_ctx, "MFALoginSetPreferred"));
|
||||
chkSetPreferred.setId("chkSetPreferred");
|
||||
boolean enablePreferred = (lstMFAMechanism.getChildren().size() > 1 && lstMFAMechanism.getSelectedIndex() > 0);
|
||||
chkSetPreferred.setVisible(enablePreferred);
|
||||
chkSetPreferred.setChecked(false);
|
||||
|
||||
int daysExpire = MSysConfig.getIntValue(MSysConfig.MFA_REGISTERED_DEVICE_EXPIRATION_DAYS, 30, Env.getAD_Client_ID(m_ctx));
|
||||
chkRegisterDevice = new Checkbox(Msg.getMsg(m_ctx, "MFALoginRegisterDevice", new Object[] {daysExpire}));
|
||||
chkRegisterDevice.setId("chkRegisterDevice");
|
||||
boolean enableRegisterDevice = (daysExpire > 0);
|
||||
chkRegisterDevice.setVisible(enableRegisterDevice);
|
||||
chkRegisterDevice.setChecked(false);
|
||||
|
||||
txtValidationCode = new Textbox();
|
||||
txtValidationCode.setId("txtValidationCode");
|
||||
txtValidationCode.setCols(25);
|
||||
ZKUpdateUtil.setWidth(txtValidationCode, "220px");
|
||||
txtValidationCode.setDisabled(true);
|
||||
this.addEventListener(ON_DEFER_LOGOUT, this);
|
||||
}
|
||||
|
||||
public void onEvent(Event event) {
|
||||
if (event.getTarget().getId().equals(ConfirmPanel.A_OK)) {
|
||||
validateMFAComplete(true);
|
||||
} else if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL)) {
|
||||
SessionManager.logoutSession();
|
||||
} else if (ON_DEFER_LOGOUT.equals(event.getName())) {
|
||||
SessionManager.logoutSession();
|
||||
}
|
||||
}
|
||||
|
||||
public void validateMFAComplete(boolean required) {
|
||||
Clients.clearBusy();
|
||||
|
||||
int registrationId = 0;
|
||||
if (required) {
|
||||
registrationId = lstMFAMechanism.getSelectedItem().getValue();
|
||||
boolean enablePreferred = (lstMFAMechanism.getChildren().size() > 1 && lstMFAMechanism.getSelectedIndex() > 0);
|
||||
chkSetPreferred.setVisible(enablePreferred);
|
||||
MMFARegistration reg = new MMFARegistration(Env.getCtx(), registrationId, null);
|
||||
if (txtValidationCode.isDisabled()) {
|
||||
String msg = reg.generateValidationCode(reg);
|
||||
lblMFAMsg.setValue(msg);
|
||||
txtValidationCode.setDisabled(false);
|
||||
lstMFAMechanism.setDisabled(true);
|
||||
AuFocus auf = new AuFocus(txtValidationCode);
|
||||
Clients.response(auf);
|
||||
return;
|
||||
} else {
|
||||
if (Util.isEmpty(txtValidationCode.getText()) && lstMFAMechanism.getItemCount() > 1) {
|
||||
lblMFAMsg.setValue(Msg.getMsg(m_ctx, "MFALoginMessage"));
|
||||
txtValidationCode.setDisabled(true);
|
||||
lstMFAMechanism.setDisabled(false);
|
||||
AuFocus auf = new AuFocus(lstMFAMechanism);
|
||||
Clients.response(auf);
|
||||
return;
|
||||
} else {
|
||||
String msg = reg.validateCode(reg, txtValidationCode.getText(), chkSetPreferred.isChecked());
|
||||
if (msg != null) {
|
||||
|
||||
String x_Forward_IP = Executions.getCurrent().getHeader("X-Forwarded-For");
|
||||
if (x_Forward_IP == null)
|
||||
x_Forward_IP = Executions.getCurrent().getRemoteAddr();
|
||||
MUser user = MUser.get(m_ctx);
|
||||
boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false);
|
||||
logAuthFailure.log(x_Forward_IP, "/webui", email_login ? user.getEMail() : user.getName(), msg);
|
||||
|
||||
// Incremental delay to avoid brute-force attack on testing codes
|
||||
try {
|
||||
Thread.sleep(failures * 2000);
|
||||
} catch (InterruptedException e) {}
|
||||
failures++;
|
||||
AuFocus auf = new AuFocus(txtValidationCode);
|
||||
Clients.response(auf);
|
||||
throw new WrongValueException(txtValidationCode, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chkRegisterDevice != null && chkRegisterDevice.isChecked()) {
|
||||
String cookieName = Env.getAD_User_ID(m_ctx) + "|" + Env.getAD_Client_ID(m_ctx);
|
||||
// TODO: generate the random cookie if possible with some fingerprint of the device
|
||||
String cookieValue = UUID.randomUUID().toString();
|
||||
setCookie(cookieName, cookieValue);
|
||||
MMFARegisteredDevice rd = new MMFARegisteredDevice(m_ctx, 0, null);
|
||||
rd.setAD_User_ID(Env.getAD_User_ID(m_ctx));
|
||||
rd.setMFADeviceIdentifier(cookieValue);
|
||||
long daysExpire = MSysConfig.getIntValue(MSysConfig.MFA_REGISTERED_DEVICE_EXPIRATION_DAYS, 30, Env.getAD_Client_ID(m_ctx));
|
||||
rd.setExpiration(new Timestamp(System.currentTimeMillis() + (daysExpire * 86400000L)));
|
||||
// TODO: rd.setHelp -> add information about the browser, device and IP address (fingerprint)
|
||||
rd.saveEx();
|
||||
}
|
||||
|
||||
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();
|
||||
FDialog.error(0, this, "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))
|
||||
FDialog.warn(0, null, "", Msg.getMsg(m_ctx, "YourPasswordWillExpireInDays",
|
||||
new Object[] { TimeUtil.getDaysBetween(now, limit) }));
|
||||
}
|
||||
}
|
||||
|
||||
Env.setContext(m_ctx, "#MFA_Registration_ID", registrationId);
|
||||
wndLogin.loginCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cookie
|
||||
* @param name
|
||||
* @param value
|
||||
*/
|
||||
public static void setCookie(String name, String value) {
|
||||
Cookie cookie = new Cookie(name, value);
|
||||
cookie.setSecure(true);
|
||||
((HttpServletResponse) Executions.getCurrent().getNativeResponse()).addCookie(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cookie by name
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static String getCookie(String name) {
|
||||
Cookie[] cookies = ((HttpServletRequest) Executions.getCurrent().getNativeRequest()).getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals(name)) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
|
||||
package org.adempiere.webui.process;
|
||||
|
||||
import org.adempiere.webui.apps.AEnv;
|
||||
import org.adempiere.webui.apps.form.MFARegisterForm;
|
||||
import org.adempiere.webui.panel.ADForm;
|
||||
import org.adempiere.webui.session.SessionManager;
|
||||
import org.adempiere.webui.util.IServerPushCallback;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.compiere.model.SystemIDs;
|
||||
import org.zkoss.zk.ui.Desktop;
|
||||
|
||||
/**
|
||||
* IDEMPIERE-4782
|
||||
* @author Carlos Ruiz - globalqss - BX Service
|
||||
*/
|
||||
public class MFARegister extends org.compiere.process.MFARegister implements IServerPushCallback {
|
||||
|
||||
/**
|
||||
* Post process to register the server push callback
|
||||
*/
|
||||
@Override
|
||||
protected void postProcess(boolean success) {
|
||||
if (success) {
|
||||
Desktop desktop = AEnv.getDesktop();
|
||||
ServerPushTemplate template = new ServerPushTemplate(desktop);
|
||||
template.executeAsync(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the complete registration form when updating the UI on server push callback
|
||||
*/
|
||||
@Override
|
||||
public void updateUI() {
|
||||
ADForm form = SessionManager.getAppDesktop().openForm(SystemIDs.FORM_MFA_REGISTER);
|
||||
if (form instanceof MFARegisterForm) {
|
||||
((MFARegisterForm)form).completeRegistration(retArray, getAD_PInstance_ID());
|
||||
}
|
||||
}
|
||||
|
||||
} // MFARegister
|
|
@ -0,0 +1,58 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Sponsor: *
|
||||
* - FH *
|
||||
* Contributors: *
|
||||
* - Carlos Ruiz *
|
||||
**********************************************************************/
|
||||
|
||||
package org.adempiere.webui.process;
|
||||
|
||||
import org.adempiere.webui.apps.IProcessParameterListener;
|
||||
import org.adempiere.webui.apps.ProcessParameterPanel;
|
||||
import org.adempiere.webui.editor.WEditor;
|
||||
import org.compiere.model.MMFAMethod;
|
||||
import org.compiere.util.Env;
|
||||
|
||||
public class MFARegisterParameterListener implements IProcessParameterListener {
|
||||
|
||||
@Override
|
||||
public void onChange(ProcessParameterPanel parameterPanel, String columnName, WEditor editor) {
|
||||
if (editor.getValue() != null) {
|
||||
if ("MFA_Method_ID".equals(columnName)) {
|
||||
Object value = editor.getValue();
|
||||
if (value != null && value instanceof Integer) {
|
||||
WEditor elementPrmEditor = parameterPanel.getEditor("MFA_ElementPrm_ID");
|
||||
Integer methodId = (Integer) value;
|
||||
if (methodId.intValue() > 0) {
|
||||
MMFAMethod method = new MMFAMethod(Env.getCtx(), methodId, null);
|
||||
// set Accounting Date when StatementDate changes
|
||||
elementPrmEditor.setValue(method.getMFA_ElementPrm_ID());
|
||||
} else {
|
||||
elementPrmEditor.setValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -43,9 +43,13 @@ public class SessionManager
|
|||
String adRoleId = Env.getContext(ctx, Env.AD_ROLE_ID);
|
||||
String adClientId = Env.getContext(ctx, Env.AD_CLIENT_ID);
|
||||
String adOrgId = Env.getContext(ctx, Env.AD_ORG_ID);
|
||||
String mfaId = Env.getContext(ctx, "#MFA_Registration_ID");
|
||||
|
||||
return (!"".equals(adUserId) && !"".equals(adRoleId)
|
||||
&& !"".equals(adClientId) && !"".equals(adOrgId));
|
||||
return ( !"".equals(mfaId)
|
||||
&& !"".equals(adOrgId)
|
||||
&& !"".equals(adUserId)
|
||||
&& !"".equals(adRoleId)
|
||||
&& !"".equals(adClientId));
|
||||
}
|
||||
|
||||
public static void setSessionApplication(IWebClient app)
|
||||
|
|
|
@ -110,6 +110,7 @@ public final class UserPreference implements Serializable {
|
|||
String attribute = PROPERTIES[i];
|
||||
String value = props.getProperty(attribute);
|
||||
|
||||
if (value != null) {
|
||||
MPreference preference = query.setParameters(new Object[]{m_AD_User_ID, attribute}).firstOnly();
|
||||
if (preference == null) {
|
||||
preference = new MUserPreference(Env.getCtx(), 0, null);
|
||||
|
@ -131,6 +132,7 @@ public final class UserPreference implements Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load user preference
|
||||
|
|
|
@ -32,6 +32,7 @@ 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.theme.ThemeManager;
|
||||
import org.compiere.model.MSysConfig;
|
||||
|
@ -61,13 +62,14 @@ public class LoginWindow extends FWindow implements EventListener<Event>
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -5169830531440825871L;
|
||||
private static final long serialVersionUID = 2783026164782754864L;
|
||||
|
||||
protected IWebClient app;
|
||||
protected Properties ctx;
|
||||
protected LoginPanel pnlLogin;
|
||||
protected ResetPasswordPanel pnlResetPassword;
|
||||
protected ChangePasswordPanel pnlChangePassword;
|
||||
protected ValidateMFAPanel pnlValidateMFA = null;
|
||||
protected RolePanel pnlRole;
|
||||
|
||||
public LoginWindow() {}
|
||||
|
@ -97,7 +99,10 @@ public class LoginWindow extends FWindow implements EventListener<Event>
|
|||
{
|
||||
createRolePanel(userName, show, clientsKNPairs);
|
||||
this.getChildren().clear();
|
||||
if (pnlRole.show())
|
||||
this.appendChild(pnlRole);
|
||||
else
|
||||
this.appendChild(pnlValidateMFA);
|
||||
}
|
||||
|
||||
protected void createRolePanel(String userName, boolean show,
|
||||
|
@ -130,6 +135,18 @@ public class LoginWindow extends FWindow implements EventListener<Event>
|
|||
pnlResetPassword = new ResetPasswordPanel(ctx, this, userName, noSecurityQuestion);
|
||||
}
|
||||
|
||||
public void validateMFA(KeyNamePair orgKNPair) {
|
||||
Clients.clearBusy();
|
||||
createValidateMFAPanel(orgKNPair);
|
||||
this.getChildren().clear();
|
||||
this.appendChild(pnlValidateMFA);
|
||||
}
|
||||
|
||||
private void createValidateMFAPanel(KeyNamePair orgKNPair) {
|
||||
if (pnlValidateMFA == null)
|
||||
pnlValidateMFA = new ValidateMFAPanel(ctx, this, orgKNPair);
|
||||
}
|
||||
|
||||
public void loginCompleted()
|
||||
{
|
||||
app.loginCompleted();
|
||||
|
@ -178,6 +195,12 @@ public class LoginWindow extends FWindow implements EventListener<Event>
|
|||
resetPasswordPanel.validate();
|
||||
return;
|
||||
}
|
||||
|
||||
ValidateMFAPanel validateMFAPanel = (ValidateMFAPanel)this.getFellowIfAny("validateMFAPanel");
|
||||
if (validateMFAPanel != null){
|
||||
validateMFAPanel.validateMFAComplete(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,6 +212,8 @@ public class LoginWindow extends FWindow implements EventListener<Event>
|
|||
public void changeRole(Locale locale, Properties ctx)
|
||||
{
|
||||
Env.setCtx(ctx);
|
||||
// clear the org ID - to force a logout if the user pushes Refresh on RolePanel
|
||||
Env.setContext(ctx, Env.AD_ORG_ID, "");
|
||||
getDesktop().getSession().setAttribute(SessionContextListener.SESSION_CTX, ctx);
|
||||
|
||||
//reload theme preference
|
||||
|
|
|
@ -162,4 +162,19 @@
|
|||
<version>1.1.0.Final</version>
|
||||
<type>jar</type>
|
||||
</location>
|
||||
<location includeSource="true" missingManifest="generate"
|
||||
type="Maven">
|
||||
<groupId>dev.samstevens.totp</groupId>
|
||||
<artifactId>totp</artifactId>
|
||||
<version>1.7.1</version>
|
||||
<type>jar</type>
|
||||
</location>
|
||||
<location includeSource="true" missingManifest="generate"
|
||||
type="Maven">
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<type>jar</type>
|
||||
</location>
|
||||
|
||||
</locations>
|
|
@ -465,5 +465,19 @@
|
|||
<version>1.1.0.Final</version>
|
||||
<type>jar</type>
|
||||
</location>
|
||||
<location includeSource="true" missingManifest="generate"
|
||||
type="Maven">
|
||||
<groupId>dev.samstevens.totp</groupId>
|
||||
<artifactId>totp</artifactId>
|
||||
<version>1.7.1</version>
|
||||
<type>jar</type>
|
||||
</location>
|
||||
<location includeSource="true" missingManifest="generate"
|
||||
type="Maven">
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<type>jar</type>
|
||||
</location>
|
||||
</locations>
|
||||
</target>
|
|
@ -346,6 +346,8 @@
|
|||
<setEntry value="slf4j.jcl@default:false"/>
|
||||
<setEntry value="stax2-api@default:default"/>
|
||||
<setEntry value="wrapped.com.google.http-client.google-http-client-gson@default:default"/>
|
||||
<setEntry value="wrapped.com.google.zxing.javase@default:default"/>
|
||||
<setEntry value="wrapped.dev.samstevens.totp.totp@default:default"/>
|
||||
<setEntry value="wrapped.io.grpc.grpc-context@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-api@default:default"/>
|
||||
<setEntry value="wrapped.io.opencensus.opencensus-contrib-http-util@default:default"/>
|
||||
|
|
Loading…
Reference in New Issue