You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2024/11/11 09:29:42 UTC
(fineract) branch develop updated: FINERACT-2081: Update password policy
This is an automated email from the ASF dual-hosted git repository.
arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 832b84f57 FINERACT-2081: Update password policy
832b84f57 is described below
commit 832b84f574212f29f58f43b03b5298aa92015bfb
Author: leksinomi <le...@gmail.com>
AuthorDate: Thu Oct 31 22:43:30 2024 +0200
FINERACT-2081: Update password policy
---
.github/workflows/build-tests.yml | 1 +
.../apache/fineract/test/api/ApiProperties.java | 2 +
.../test/stepdef/common/BatchApiStepDef.java | 4 +-
.../fineract/test/stepdef/common/UserStepDef.java | 4 +-
.../test/stepdef/loan/LoanDelinquencyStepDef.java | 4 +-
.../test/stepdef/loan/LoanRepaymentStepDef.java | 4 +-
.../resources/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 +-
.../LoanTransactionAuditingIntegrationTest.java | 4 +-
.../LoanValidationIntegrationTest.java | 2 +-
.../integrationtests/MakercheckerTest.java | 8 +-
.../integrationtests/NotificationApiTest.java | 3 +-
.../PasswordPreferencesIntegrationTest.java | 7 ++
.../integrationtests/UserAdministrationTest.java | 44 +++++++++-
.../useradministration/users/UserHelper.java | 21 ++++-
19 files changed, 191 insertions(+), 25 deletions(-)
diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml
index da0c7d4a8..e53a91832 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: true
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 417685a13..db76dddc2 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 13889c4e5..fde636e62 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 class BatchApiStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> 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 class BatchApiStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> 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 ab39b3062..a4606f568 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 class UserStepDef extends AbstractStepDef {
.lastname(username) //
.sendPasswordToEmail(Boolean.FALSE) //
.officeId(1L) //
- .password(apiProperties.getPassword()) //
- .repeatPassword(apiProperties.getPassword()) //
+ .password(apiProperties.getStrongPassword()) //
+ .repeatPassword(apiProperties.getStrongPassword()) //
.roles(List.of(roleId));
Response<PostUsersResponse> 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 963749f77..707040b7d 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
@@ -225,7 +225,7 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> 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));
@@ -257,7 +257,7 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> 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 dc0be177f..d33e60762 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
@@ -161,7 +161,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> 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));
@@ -222,7 +222,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> 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 d9d724678..63365475e 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 8ac88161c..7b79a6754 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 @@
<include file="parts/0149_update_global_configuration_names.xml" relativeToChangelogFile="true" />
<include file="parts/0150_transaction_summary_with_asset_owner_report_interest_waiver_interest_refund_added.xml" relativeToChangelogFile="true" />
<include file="parts/0151_interest_refund_business_events.xml" relativeToChangelogFile="true" />
+ <include file="parts/0152_update_password_validation_policy.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
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 000000000..0bd260841
--- /dev/null
+++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0152_update_password_validation_policy.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
+ <changeSet author="fineract" id="1" context="mysql">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">
+ SELECT COUNT(*) FROM m_password_validation_policy WHERE `key` = 'strong'
+ </sqlCheck>
+ </preConditions>
+
+ <insert tableName="m_password_validation_policy">
+ <column name="regex" value="^(?!.*(.)\1)(?!.*\s)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^\w\s]).{12,50}$"/>
+ <column name="description" value="Password must be 12 to 50 characters long, containing at least one uppercase letter, one lowercase letter, one numeric digit, and one special character, with no spaces or consecutive repeating characters"/>
+ <column name="active" valueBoolean="false"/>
+ <column name="key" value="strong"/>
+ </insert>
+ </changeSet>
+ <changeSet author="fineract" id="1" context="postgresql">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">
+ SELECT COUNT(*) FROM m_password_validation_policy WHERE key = 'strong'
+ </sqlCheck>
+ </preConditions>
+
+ <insert tableName="m_password_validation_policy">
+ <column name="regex" value="^(?!.*(.)\1)(?!.*\s)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^\w\s]).{12,50}$"/>
+ <column name="description" value="Password must be 12 to 50 characters long, containing at least one uppercase letter, one lowercase letter, one numeric digit, and one special character, with no spaces or consecutive repeating characters"/>
+ <column name="active" valueBoolean="false"/>
+ <column name="key" value="strong"/>
+ </insert>
+ </changeSet>
+
+ <changeSet author="fineract" id="2" context="mysql">
+ <preConditions onFail="MARK_RAN">
+ <and>
+ <sqlCheck expectedResult="1">
+ SELECT COUNT(*) FROM m_password_validation_policy WHERE `key` = 'simple' AND active = 1;
+ </sqlCheck>
+ <sqlCheck expectedResult="0">
+ SELECT COUNT(*) FROM m_password_validation_policy WHERE `key` = 'strong' AND active = 1;
+ </sqlCheck>
+ </and>
+ </preConditions>
+
+ <update tableName="m_password_validation_policy">
+ <column name="active" valueBoolean="false"/>
+ <where>`key` = 'simple' AND active = true</where>
+ </update>
+ <update tableName="m_password_validation_policy">
+ <column name="active" valueBoolean="true"/>
+ <where>`key` = 'strong' AND active = false</where>
+ </update>
+ </changeSet>
+ <changeSet author="fineract" id="2" context="postgresql">
+ <preConditions onFail="MARK_RAN">
+ <and>
+ <sqlCheck expectedResult="1">
+ SELECT COUNT(*) FROM m_password_validation_policy WHERE key = 'simple' AND active = TRUE;
+ </sqlCheck>
+ <sqlCheck expectedResult="0">
+ SELECT COUNT(*) FROM m_password_validation_policy WHERE key = 'strong' AND active = TRUE;
+ </sqlCheck>
+ </and>
+ </preConditions>
+
+ <update tableName="m_password_validation_policy">
+ <column name="active" valueBoolean="false"/>
+ <where>key = 'simple' AND active = TRUE</where>
+ </update>
+ <update tableName="m_password_validation_policy">
+ <column name="active" valueBoolean="true"/>
+ <where>key = 'strong' AND active = FALSE</where>
+ </update>
+ </changeSet>
+</databaseChangeLog>
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 33b407918..b8e4792f3 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 class AuthenticationIntegrationTest {
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 d66990803..873a72ca5 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 class ClientAuditingIntegrationTest {
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 class ClientAuditingIntegrationTest {
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 5498d7207..e5ef1220b 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 class LoanAuditingIntegrationTest {
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 class LoanAuditingIntegrationTest {
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 161947b8b..6f2de8d6a 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 class LoanTransactionAuditingIntegrationTest {
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 class LoanTransactionAuditingIntegrationTest {
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 abbc9279a..dbad3e796 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 class LoanValidationIntegrationTest {
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 1e96e3efb..91dd1d097 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 class MakercheckerTest {
// 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 class MakercheckerTest {
// 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 307b7bc41..c0ae80244 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 class NotificationApiTest {
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 fa3af54c7..e93c81239 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 java.util.List;
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 class PasswordPreferencesIntegrationTest {
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 b54b96e7f..98a521c6c 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 class UserAdministrationTest extends IntegrationTest {
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 class UserAdministrationTest extends IntegrationTest {
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 class UserAdministrationTest extends IntegrationTest {
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 class UserAdministrationTest extends IntegrationTest {
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<String, String> 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 bdbfa402a..eca6a0bea 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 final class UserHelper {
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 final class UserHelper {
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);