From 3728a137093a5a12d5d186e8b2a3e201b7e02ddd Mon Sep 17 00:00:00 2001 From: leksinomi Date: Thu, 31 Oct 2024 22:43:30 +0200 Subject: [PATCH] FINERACT-2081: Update password policy --- .github/workflows/build-tests.yml | 1 + .../fineract/test/api/ApiProperties.java | 2 + .../test/stepdef/common/BatchApiStepDef.java | 4 +- .../test/stepdef/common/UserStepDef.java | 4 +- .../stepdef/loan/LoanDelinquencyStepDef.java | 4 +- .../stepdef/loan/LoanRepaymentStepDef.java | 4 +- .../fineract-test-application.properties | 1 + .../db/changelog/tenant/changelog-tenant.xml | 1 + ...0152_update_password_validation_policy.xml | 96 +++++++++++++++++++ .../AuthenticationIntegrationTest.java | 2 +- .../ClientAuditingIntegrationTest.java | 4 +- .../LoanAuditingIntegrationTest.java | 4 +- ...oanTransactionAuditingIntegrationTest.java | 4 +- .../LoanValidationIntegrationTest.java | 2 +- .../integrationtests/MakercheckerTest.java | 8 +- .../integrationtests/NotificationApiTest.java | 3 +- .../PasswordPreferencesIntegrationTest.java | 7 ++ .../UserAdministrationTest.java | 44 ++++++++- .../useradministration/users/UserHelper.java | 21 +++- 19 files changed, 191 insertions(+), 25 deletions(-) create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0152_update_password_validation_policy.xml diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index 71fc12d6fd8..e67ee5ed4a4 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -37,6 +37,7 @@ jobs: BASE_URL: https://localhost:8443 TEST_USERNAME: mifos TEST_PASSWORD: password + TEST_STRONG_PASSWORD: A1b2c3d4e5f$ TEST_TENANT_ID: default INITIALIZATION_ENABLED: true EVENT_VERIFICATION_ENABLED: false diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java index 417685a13a6..db76dddc2aa 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java @@ -32,6 +32,8 @@ public class ApiProperties { private String username; @Value("${fineract-test.api.password}") private String password; + @Value("${fineract-test.api.strong-password}") + private String strongPassword; @Value("${fineract-test.api.tenant-id}") private String tenantId; } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java index 92d5dd3d940..2c3d9095071 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java @@ -473,7 +473,7 @@ public void runBatchApiCreateAndApproveLoanRescheduleWithGivenUser(String fromDa Long createdUserId = createUserResponse.body().getResourceId(); Response user = usersApi.retrieveOne31(createdUserId).execute(); ErrorHelper.checkSuccessfulApiCall(user); - String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword(); Base64 base64 = new Base64(); headerMap.put("Authorization", "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); @@ -533,7 +533,7 @@ public void runBatchApiCreateAndApproveLoanRescheduleWithGivenUserLockedByCobErr Long createdUserId = createUserResponse.body().getResourceId(); Response user = usersApi.retrieveOne31(createdUserId).execute(); ErrorHelper.checkSuccessfulApiCall(user); - String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword(); Base64 base64 = new Base64(); headerMap.put("Authorization", "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/UserStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/UserStepDef.java index ab39b306219..a4606f5684d 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/UserStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/UserStepDef.java @@ -76,8 +76,8 @@ public void createUserWithUsernameAndRoles(String username, String roleName, Lis .lastname(username) // .sendPasswordToEmail(Boolean.FALSE) // .officeId(1L) // - .password(apiProperties.getPassword()) // - .repeatPassword(apiProperties.getPassword()) // + .password(apiProperties.getStrongPassword()) // + .repeatPassword(apiProperties.getStrongPassword()) // .roles(List.of(roleId)); Response createUserResponse = usersApi.create15(postUsersRequest).execute(); diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java index e55519460e1..6844a1929aa 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java @@ -226,7 +226,7 @@ public void delinquencyPauseWithCreatedUser(String startDate, String endDate) th Long createdUserId = createUserResponse.body().getResourceId(); Response user = usersApi.retrieveOne31(createdUserId).execute(); ErrorHelper.checkSuccessfulApiCall(user); - String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword(); Base64 base64 = new Base64(); headerMap.put("Authorization", "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); @@ -258,7 +258,7 @@ public void delinquencyPauseWithCreatedUserNOPermissionError(String startDate, S Long createdUserId = createUserResponse.body().getResourceId(); Response user = usersApi.retrieveOne31(createdUserId).execute(); ErrorHelper.checkSuccessfulApiCall(user); - String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword(); Base64 base64 = new Base64(); headerMap.put("Authorization", "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanRepaymentStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanRepaymentStepDef.java index 206abd1a014..743e31bb27a 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanRepaymentStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanRepaymentStepDef.java @@ -155,7 +155,7 @@ public void makeRepaymentWithGivenUser(String repaymentType, String transactionD Long createdUserId = createUserResponse.body().getResourceId(); Response user = usersApi.retrieveOne31(createdUserId).execute(); ErrorHelper.checkSuccessfulApiCall(user); - String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword(); Base64 base64 = new Base64(); headerMap.put("Authorization", "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); @@ -214,7 +214,7 @@ public void makeRepaymentWithGivenUserByExternalId(String repaymentType, String Long createdUserId = createUserResponse.body().getResourceId(); Response user = usersApi.retrieveOne31(createdUserId).execute(); ErrorHelper.checkSuccessfulApiCall(user); - String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword(); Base64 base64 = new Base64(); headerMap.put("Authorization", "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); diff --git a/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties b/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties index d9d724678f9..63365475e4b 100644 --- a/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties +++ b/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties @@ -20,6 +20,7 @@ fineract-test.api.base-url=${BASE_URL:https://localhost:8443} fineract-test.api.username=${TEST_USERNAME:mifos} fineract-test.api.password=${TEST_PASSWORD:password} +fineract-test.api.strong-password=${TEST_STRONG_PASSWORD:A1b2c3d4e5f$} fineract-test.api.tenant-id=${TEST_TENANT_ID:default} fineract-test.initialization.enabled=${INITIALIZATION_ENABLED:false} diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 8ac88161cf7..7b79a6754f1 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -170,4 +170,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0152_update_password_validation_policy.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0152_update_password_validation_policy.xml new file mode 100644 index 00000000000..0bd2608415e --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0152_update_password_validation_policy.xml @@ -0,0 +1,96 @@ + + + + + + + SELECT COUNT(*) FROM m_password_validation_policy WHERE `key` = 'strong' + + + + + + + + + + + + + + SELECT COUNT(*) FROM m_password_validation_policy WHERE key = 'strong' + + + + + + + + + + + + + + + + SELECT COUNT(*) FROM m_password_validation_policy WHERE `key` = 'simple' AND active = 1; + + + SELECT COUNT(*) FROM m_password_validation_policy WHERE `key` = 'strong' AND active = 1; + + + + + + + `key` = 'simple' AND active = true + + + + `key` = 'strong' AND active = false + + + + + + + SELECT COUNT(*) FROM m_password_validation_policy WHERE key = 'simple' AND active = TRUE; + + + SELECT COUNT(*) FROM m_password_validation_policy WHERE key = 'strong' AND active = TRUE; + + + + + + + key = 'simple' AND active = TRUE + + + + key = 'strong' AND active = FALSE + + + diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuthenticationIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuthenticationIntegrationTest.java index 33b40791855..b8e4792f344 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuthenticationIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuthenticationIntegrationTest.java @@ -64,7 +64,7 @@ public void setup() { AccountHelper accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); String username = Utils.uniqueRandomStringGenerator("user", 8); - UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "P4ssw0rd", "resourceId"); + UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", "resourceId"); Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); Integer loanProductID = setupLoanProduct(accountHelper); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientAuditingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientAuditingIntegrationTest.java index d6699080306..873a72ca5ea 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientAuditingIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientAuditingIntegrationTest.java @@ -65,7 +65,7 @@ public void setup() { public void checkAuditDates() throws InterruptedException { final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); String username = Utils.uniqueRandomStringGenerator("user", 8); - final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "password", + final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", "resourceId"); OffsetDateTime now = Utils.getAuditDateTimeToCompare(); LOG.info("-------------------------Creating Client---------------------------"); @@ -88,7 +88,7 @@ public void checkAuditDates() throws InterruptedException { LOG.info("-------------------------Modify Client with System user---------------------------"); this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec.header("Authorization", - "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "password")); + "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$")); this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java index 5498d72075d..e5ef1220b4f 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java @@ -79,7 +79,7 @@ public void setup() { public void checkAuditDates() throws InterruptedException { final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); String username = Utils.uniqueRandomStringGenerator("user", 8); - final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "P4ssw0rd", + final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", "resourceId"); LOG.info("-------------------------Creating Client---------------------------"); @@ -119,7 +119,7 @@ public void checkAuditDates() throws InterruptedException { this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec.header("Authorization", - "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "P4ssw0rd")); + "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$")); this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java index 161947b8b15..6f2de8d6a6f 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionAuditingIntegrationTest.java @@ -79,7 +79,7 @@ public void setup() { public void checkAuditDates() throws InterruptedException { final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); String username = Utils.uniqueRandomStringGenerator("user", 8); - final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "P4ssw0rd", + final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", "resourceId"); LOG.info("-------------------------Creating Client---------------------------"); @@ -128,7 +128,7 @@ public void checkAuditDates() throws InterruptedException { this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec.header("Authorization", - "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "P4ssw0rd")); + "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$")); this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java index abbc9279a60..dbad3e796ae 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java @@ -69,7 +69,7 @@ public void setup() { public void checkPrincipalErrors() { final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); String username = Utils.uniqueRandomStringGenerator("user", 8); - UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "P4ssw0rd", "resourceId"); + UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", "resourceId"); LOG.info("-------------------------Creating Client---------------------------"); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/MakercheckerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/MakercheckerTest.java index 1e96e3efb67..91dd1d097e3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/MakercheckerTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/MakercheckerTest.java @@ -106,11 +106,11 @@ public void testMakerCheckerOn() { // create maker user String maker = Utils.uniqueRandomStringGenerator("user", 8); final Integer makerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker, - "P4ssw0rd", "resourceId"); + "A1b2c3d4e5f$", "resourceId"); // create client - maker-checker disabled RequestSpecification makerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build() - .header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker, "P4ssw0rd")); + .header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker, "A1b2c3d4e5f$")); Integer clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec); assertNotNull(clientId); ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId); @@ -155,9 +155,9 @@ public void testMakerCheckerOn() { // create checker user String checker = Utils.uniqueRandomStringGenerator("user", 8); final Integer checkerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, checker, - "P4ssw0rd", "resourceId"); + "A1b2c3d4e5f$", "resourceId"); RequestSpecification checkerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build() - .header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(checker, "P4ssw0rd")); + .header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(checker, "A1b2c3d4e5f$")); // check by another checker user should succeed HashMap response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, clientCommandId); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotificationApiTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotificationApiTest.java index 307b7bc418a..c0ae8024424 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotificationApiTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotificationApiTest.java @@ -61,7 +61,8 @@ public void setUp() { GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); String username = Utils.uniqueRandomStringGenerator("NotificationUser", 4); - String password = Utils.randomStringGenerator("aA1", 10); // prefix is to conform with the password rules + String password = Utils.randomStringGenerator("A1b2c3d4e5f$", 1); // prefix is to conform with the password + // rules PostUsersRequest createUserRequest = new PostUsersRequest().username(username) .firstname(Utils.randomStringGenerator("NotificationFN", 4)).lastname(Utils.randomStringGenerator("NotificationLN", 4)) .email("whatever@mifos.org").password(password).repeatPassword(password).sendPasswordToEmail(false) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/PasswordPreferencesIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/PasswordPreferencesIntegrationTest.java index fa3af54c7b6..e93c812390c 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/PasswordPreferencesIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/PasswordPreferencesIntegrationTest.java @@ -30,6 +30,7 @@ import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.PasswordPreferencesHelper; import org.apache.fineract.integrationtests.common.Utils; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -42,6 +43,7 @@ public class PasswordPreferencesIntegrationTest { private ResponseSpecification responseSpec; private RequestSpecification requestSpec; private ResponseSpecification generalResponseSpec; + private int originalPasswordPolicyId; @BeforeEach public void setUp() { @@ -50,7 +52,12 @@ public void setUp() { this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); this.generalResponseSpec = new ResponseSpecBuilder().build(); + originalPasswordPolicyId = PasswordPreferencesHelper.getActivePasswordPreference(requestSpec, responseSpec); + } + @AfterEach + void tearDown() { + PasswordPreferencesHelper.updatePasswordPreferences(requestSpec, responseSpec, Integer.toString(originalPasswordPolicyId)); } @Test diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UserAdministrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UserAdministrationTest.java index b54b96e7fbd..98a521c6c80 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UserAdministrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UserAdministrationTest.java @@ -19,6 +19,7 @@ package org.apache.fineract.integrationtests; +import com.google.gson.JsonObject; import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; @@ -185,7 +186,7 @@ public void testModifySystemUser() { public void testApplicationUserCanChangeOwnPassword() { // Admin creates a new user with an empty role Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); - String originalPassword = "aA1qwerty56"; + String originalPassword = "QwE!5rTy#9uP0"; String simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4); GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); PostUsersRequest createUserRequest = new PostUsersRequest().username(simpleUsername) @@ -198,7 +199,7 @@ public void testApplicationUserCanChangeOwnPassword() { Assertions.assertNotNull(userId); // User updates its own password - String updatedPassword = "aA1qwerty56!"; + String updatedPassword = "QwE!5rTy#9uP0u"; PutUsersUserIdResponse putUsersUserIdResponse = ok(newFineract(simpleUsername, originalPassword).users.update26(userId, new PutUsersUserIdRequest().password(updatedPassword).repeatPassword(updatedPassword))); Assertions.assertNotNull(putUsersUserIdResponse.getResourceId()); @@ -218,7 +219,7 @@ public void testApplicationUserCanChangeOwnPassword() { public void testApplicationUserShallNotBeAbleToChangeItsOwnRoles() { // Admin creates a new user with one role assigned Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); - String password = "aA1qwerty56"; + String password = "QwE!5rTy#9uP0"; String simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4); GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); PostUsersRequest createUserRequest = new PostUsersRequest().username(simpleUsername) @@ -243,4 +244,41 @@ public void testApplicationUserShallNotBeAbleToChangeItsOwnRoles() { Assertions.assertTrue(callFailedRuntimeException.getMessage().contains("not.enough.permission.to.update.fields")); } + @Test + public void testUserCreationWithValidPassword() { + String validPassword = "Abcdef1#2$3%XYZ"; + + PostUsersRequest createUserRequest = UserHelper.buildUserRequest(responseSpec, requestSpec, validPassword); + PostUsersResponse userCreationResponse = UserHelper.createUser(requestSpec, responseSpec, createUserRequest); + + Assertions.assertNotNull(userCreationResponse.getResourceId()); + } + + @Test + public void testUserCreationWithInvalidPasswords() { + Map invalidPasswords = Map.ofEntries(Map.entry("TooShort", "Ab1#Xyz"), // Less than 12 + // characters + Map.entry("NoUppercase", "abcdefg1#2$3%xyz"), // Missing uppercase letter + Map.entry("NoLowercase", "ABCDEFG1#2$3%XYZ"), // Missing lowercase letter + Map.entry("NoDigit", "Abcdefg#@$%XYZabc"), // Missing digit + Map.entry("NoSpecialChar", "Abcdefg123456XYZ"), // Missing special character + Map.entry("ContainsWhitespace", "Abcdefg1# 2$3%"), // Contains whitespace + Map.entry("RepeatedCharacters", "AAbbcc11##$$%%YY") // Contains repeated characters + ); + this.responseSpec = new ResponseSpecBuilder().build(); + + invalidPasswords.forEach((description, password) -> { + PostUsersRequest createUserRequest = UserHelper.buildUserRequest(responseSpec, requestSpec, password); + JsonObject jsonResponse = UserHelper.createUserWithJsonResponse(requestSpec, responseSpec, createUserRequest); + Assertions.assertEquals("400", jsonResponse.get("httpStatusCode").getAsString(), "Expected HTTP 400 for: " + description); + Assertions.assertEquals("validation.msg.validation.errors.exist", + jsonResponse.get("userMessageGlobalisationCode").getAsString(), "Expected user message code for: " + description); + + JsonObject errorDetails = jsonResponse.getAsJsonArray("errors").get(0).getAsJsonObject(); + Assertions.assertEquals("password", errorDetails.get("parameterName").getAsString(), + "Expected validation error parameter name for: " + description); + Assertions.assertEquals("validation.msg.user.password.does.not.match.regexp", + errorDetails.get("userMessageGlobalisationCode").getAsString(), "Expected validation code for: " + description); + }); + } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/useradministration/users/UserHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/useradministration/users/UserHelper.java index bdbfa402af1..eca6a0bea93 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/useradministration/users/UserHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/useradministration/users/UserHelper.java @@ -19,6 +19,8 @@ package org.apache.fineract.integrationtests.useradministration.users; import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import io.restassured.builder.RequestSpecBuilder; import io.restassured.http.ContentType; import io.restassured.path.json.JsonPath; @@ -44,7 +46,7 @@ public final class UserHelper { private static final String READ_LOAN_PERMISSION = "READ_LOAN"; public static final String SIMPLE_USER_NAME = Utils.uniqueRandomStringGenerator("NotificationUser", 4); - public static final String SIMPLE_USER_PASSWORD = "aA1qwerty56"; + public static final String SIMPLE_USER_PASSWORD = "QwE!5rTy#9uP0"; private static boolean SIMPLE_USER_CREATED = false; private UserHelper() {} @@ -73,6 +75,13 @@ public static PostUsersResponse createUser(final RequestSpecification requestSpe return GSON.fromJson(response, PostUsersResponse.class); } + public static JsonObject createUserWithJsonResponse(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + PostUsersRequest request) { + String requestBody = GSON.toJson(request); + String jsonResponse = Utils.performServerPost(requestSpec, responseSpec, CREATE_USER_URL, requestBody); + return JsonParser.parseString(jsonResponse).getAsJsonObject(); + } + public static Object createUserForSelfService(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, int roleId, int staffId, int clientId, String attribute) { return Utils.performServerPost(requestSpec, responseSpec, CREATE_USER_URL, @@ -161,6 +170,16 @@ public static RequestSpecification getSimpleUserWithoutBypassPermission(final Re return responseRequestSpec; } + public static PostUsersRequest buildUserRequest(ResponseSpecification responseSpec, RequestSpecification requestSpec, String password) { + Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); + String uniqueUsername = Utils.uniqueRandomStringGenerator("TestUser", 4); + GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); + + return new PostUsersRequest().username(uniqueUsername).firstname("Test").lastname("User").email("testuser@example.com") + .password(password).repeatPassword(password).sendPasswordToEmail(false).officeId(headOffice.getId()) + .roles(List.of(roleId.longValue())); + } + private static String createSimpleRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); addRepaymentPermissionToRole(requestSpec, responseSpec, roleId);