FINERACT-2081: Update password policy

This commit is contained in:
leksinomi
2024-11-11 10:29:36 +01:00
committed by Arnold Gálovics
parent 975a176610
commit 832b84f574
19 changed files with 191 additions and 25 deletions
+1
View File
@@ -37,6 +37,7 @@ jobs:
BASE_URL: https://localhost:8443 BASE_URL: https://localhost:8443
TEST_USERNAME: mifos TEST_USERNAME: mifos
TEST_PASSWORD: password TEST_PASSWORD: password
TEST_STRONG_PASSWORD: A1b2c3d4e5f$
TEST_TENANT_ID: default TEST_TENANT_ID: default
INITIALIZATION_ENABLED: true INITIALIZATION_ENABLED: true
EVENT_VERIFICATION_ENABLED: true EVENT_VERIFICATION_ENABLED: true
@@ -32,6 +32,8 @@ public class ApiProperties {
private String username; private String username;
@Value("${fineract-test.api.password}") @Value("${fineract-test.api.password}")
private String password; private String password;
@Value("${fineract-test.api.strong-password}")
private String strongPassword;
@Value("${fineract-test.api.tenant-id}") @Value("${fineract-test.api.tenant-id}")
private String tenantId; private String tenantId;
} }
@@ -473,7 +473,7 @@ public class BatchApiStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId(); Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute(); Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
ErrorHelper.checkSuccessfulApiCall(user); ErrorHelper.checkSuccessfulApiCall(user);
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword();
Base64 base64 = new Base64(); Base64 base64 = new Base64();
headerMap.put("Authorization", headerMap.put("Authorization",
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); "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(); Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute(); Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
ErrorHelper.checkSuccessfulApiCall(user); ErrorHelper.checkSuccessfulApiCall(user);
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword();
Base64 base64 = new Base64(); Base64 base64 = new Base64();
headerMap.put("Authorization", headerMap.put("Authorization",
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
@@ -76,8 +76,8 @@ public class UserStepDef extends AbstractStepDef {
.lastname(username) // .lastname(username) //
.sendPasswordToEmail(Boolean.FALSE) // .sendPasswordToEmail(Boolean.FALSE) //
.officeId(1L) // .officeId(1L) //
.password(apiProperties.getPassword()) // .password(apiProperties.getStrongPassword()) //
.repeatPassword(apiProperties.getPassword()) // .repeatPassword(apiProperties.getStrongPassword()) //
.roles(List.of(roleId)); .roles(List.of(roleId));
Response<PostUsersResponse> createUserResponse = usersApi.create15(postUsersRequest).execute(); Response<PostUsersResponse> createUserResponse = usersApi.create15(postUsersRequest).execute();
@@ -225,7 +225,7 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId(); Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute(); Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
ErrorHelper.checkSuccessfulApiCall(user); ErrorHelper.checkSuccessfulApiCall(user);
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword();
Base64 base64 = new Base64(); Base64 base64 = new Base64();
headerMap.put("Authorization", headerMap.put("Authorization",
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); "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(); Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute(); Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
ErrorHelper.checkSuccessfulApiCall(user); ErrorHelper.checkSuccessfulApiCall(user);
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword();
Base64 base64 = new Base64(); Base64 base64 = new Base64();
headerMap.put("Authorization", headerMap.put("Authorization",
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
@@ -161,7 +161,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
Long createdUserId = createUserResponse.body().getResourceId(); Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute(); Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
ErrorHelper.checkSuccessfulApiCall(user); ErrorHelper.checkSuccessfulApiCall(user);
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword();
Base64 base64 = new Base64(); Base64 base64 = new Base64();
headerMap.put("Authorization", headerMap.put("Authorization",
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); "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(); Long createdUserId = createUserResponse.body().getResourceId();
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute(); Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
ErrorHelper.checkSuccessfulApiCall(user); ErrorHelper.checkSuccessfulApiCall(user);
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); String authorizationString = user.body().getUsername() + ":" + apiProperties.getStrongPassword();
Base64 base64 = new Base64(); Base64 base64 = new Base64();
headerMap.put("Authorization", headerMap.put("Authorization",
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
@@ -20,6 +20,7 @@
fineract-test.api.base-url=${BASE_URL:https://localhost:8443} fineract-test.api.base-url=${BASE_URL:https://localhost:8443}
fineract-test.api.username=${TEST_USERNAME:mifos} fineract-test.api.username=${TEST_USERNAME:mifos}
fineract-test.api.password=${TEST_PASSWORD:password} 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.api.tenant-id=${TEST_TENANT_ID:default}
fineract-test.initialization.enabled=${INITIALIZATION_ENABLED:false} fineract-test.initialization.enabled=${INITIALIZATION_ENABLED:false}
@@ -170,4 +170,5 @@
<include file="parts/0149_update_global_configuration_names.xml" relativeToChangelogFile="true" /> <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/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/0151_interest_refund_business_events.xml" relativeToChangelogFile="true" />
<include file="parts/0152_update_password_validation_policy.xml" relativeToChangelogFile="true" />
</databaseChangeLog> </databaseChangeLog>
@@ -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>
@@ -64,7 +64,7 @@ public class AuthenticationIntegrationTest {
AccountHelper accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); AccountHelper accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
String username = Utils.uniqueRandomStringGenerator("user", 8); 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 clientID = ClientHelper.createClient(requestSpec, responseSpec);
Integer loanProductID = setupLoanProduct(accountHelper); Integer loanProductID = setupLoanProduct(accountHelper);
@@ -65,7 +65,7 @@ public class ClientAuditingIntegrationTest {
public void checkAuditDates() throws InterruptedException { public void checkAuditDates() throws InterruptedException {
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
String username = Utils.uniqueRandomStringGenerator("user", 8); 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"); "resourceId");
OffsetDateTime now = Utils.getAuditDateTimeToCompare(); OffsetDateTime now = Utils.getAuditDateTimeToCompare();
LOG.info("-------------------------Creating Client---------------------------"); LOG.info("-------------------------Creating Client---------------------------");
@@ -88,7 +88,7 @@ public class ClientAuditingIntegrationTest {
LOG.info("-------------------------Modify Client with System user---------------------------"); LOG.info("-------------------------Modify Client with System user---------------------------");
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", this.requestSpec.header("Authorization",
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "password")); "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$"));
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare();
@@ -79,7 +79,7 @@ public class LoanAuditingIntegrationTest {
public void checkAuditDates() throws InterruptedException { public void checkAuditDates() throws InterruptedException {
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
String username = Utils.uniqueRandomStringGenerator("user", 8); 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"); "resourceId");
LOG.info("-------------------------Creating Client---------------------------"); LOG.info("-------------------------Creating Client---------------------------");
@@ -119,7 +119,7 @@ public class LoanAuditingIntegrationTest {
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", this.requestSpec.header("Authorization",
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "P4ssw0rd")); "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$"));
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare();
@@ -79,7 +79,7 @@ public class LoanTransactionAuditingIntegrationTest {
public void checkAuditDates() throws InterruptedException { public void checkAuditDates() throws InterruptedException {
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
String username = Utils.uniqueRandomStringGenerator("user", 8); 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"); "resourceId");
LOG.info("-------------------------Creating Client---------------------------"); LOG.info("-------------------------Creating Client---------------------------");
@@ -128,7 +128,7 @@ public class LoanTransactionAuditingIntegrationTest {
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", this.requestSpec.header("Authorization",
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "P4ssw0rd")); "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$"));
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare();
@@ -69,7 +69,7 @@ public class LoanValidationIntegrationTest {
public void checkPrincipalErrors() { public void checkPrincipalErrors() {
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
String username = Utils.uniqueRandomStringGenerator("user", 8); 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---------------------------"); LOG.info("-------------------------Creating Client---------------------------");
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
@@ -106,11 +106,11 @@ public class MakercheckerTest {
// create maker user // create maker user
String maker = Utils.uniqueRandomStringGenerator("user", 8); String maker = Utils.uniqueRandomStringGenerator("user", 8);
final Integer makerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker, final Integer makerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker,
"P4ssw0rd", "resourceId"); "A1b2c3d4e5f$", "resourceId");
// create client - maker-checker disabled // create client - maker-checker disabled
RequestSpecification makerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build() 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); Integer clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
assertNotNull(clientId); assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId); ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId);
@@ -155,9 +155,9 @@ public class MakercheckerTest {
// create checker user // create checker user
String checker = Utils.uniqueRandomStringGenerator("user", 8); String checker = Utils.uniqueRandomStringGenerator("user", 8);
final Integer checkerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, checker, 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() 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 // check by another checker user should succeed
HashMap<?, ?> response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, clientCommandId); HashMap<?, ?> response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, clientCommandId);
@@ -61,7 +61,8 @@ public class NotificationApiTest {
GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec);
String username = Utils.uniqueRandomStringGenerator("NotificationUser", 4); 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) PostUsersRequest createUserRequest = new PostUsersRequest().username(username)
.firstname(Utils.randomStringGenerator("NotificationFN", 4)).lastname(Utils.randomStringGenerator("NotificationLN", 4)) .firstname(Utils.randomStringGenerator("NotificationFN", 4)).lastname(Utils.randomStringGenerator("NotificationLN", 4))
.email("whatever@mifos.org").password(password).repeatPassword(password).sendPasswordToEmail(false) .email("whatever@mifos.org").password(password).repeatPassword(password).sendPasswordToEmail(false)
@@ -30,6 +30,7 @@ import java.util.List;
import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.PasswordPreferencesHelper; import org.apache.fineract.integrationtests.common.PasswordPreferencesHelper;
import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -42,6 +43,7 @@ public class PasswordPreferencesIntegrationTest {
private ResponseSpecification responseSpec; private ResponseSpecification responseSpec;
private RequestSpecification requestSpec; private RequestSpecification requestSpec;
private ResponseSpecification generalResponseSpec; private ResponseSpecification generalResponseSpec;
private int originalPasswordPolicyId;
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
@@ -50,7 +52,12 @@ public class PasswordPreferencesIntegrationTest {
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.generalResponseSpec = new ResponseSpecBuilder().build(); this.generalResponseSpec = new ResponseSpecBuilder().build();
originalPasswordPolicyId = PasswordPreferencesHelper.getActivePasswordPreference(requestSpec, responseSpec);
}
@AfterEach
void tearDown() {
PasswordPreferencesHelper.updatePasswordPreferences(requestSpec, responseSpec, Integer.toString(originalPasswordPolicyId));
} }
@Test @Test
@@ -19,6 +19,7 @@
package org.apache.fineract.integrationtests; package org.apache.fineract.integrationtests;
import com.google.gson.JsonObject;
import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder; import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
@@ -185,7 +186,7 @@ public class UserAdministrationTest extends IntegrationTest {
public void testApplicationUserCanChangeOwnPassword() { public void testApplicationUserCanChangeOwnPassword() {
// Admin creates a new user with an empty role // Admin creates a new user with an empty role
Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
String originalPassword = "aA1qwerty56"; String originalPassword = "QwE!5rTy#9uP0";
String simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4); String simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4);
GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec);
PostUsersRequest createUserRequest = new PostUsersRequest().username(simpleUsername) PostUsersRequest createUserRequest = new PostUsersRequest().username(simpleUsername)
@@ -198,7 +199,7 @@ public class UserAdministrationTest extends IntegrationTest {
Assertions.assertNotNull(userId); Assertions.assertNotNull(userId);
// User updates its own password // User updates its own password
String updatedPassword = "aA1qwerty56!"; String updatedPassword = "QwE!5rTy#9uP0u";
PutUsersUserIdResponse putUsersUserIdResponse = ok(newFineract(simpleUsername, originalPassword).users.update26(userId, PutUsersUserIdResponse putUsersUserIdResponse = ok(newFineract(simpleUsername, originalPassword).users.update26(userId,
new PutUsersUserIdRequest().password(updatedPassword).repeatPassword(updatedPassword))); new PutUsersUserIdRequest().password(updatedPassword).repeatPassword(updatedPassword)));
Assertions.assertNotNull(putUsersUserIdResponse.getResourceId()); Assertions.assertNotNull(putUsersUserIdResponse.getResourceId());
@@ -218,7 +219,7 @@ public class UserAdministrationTest extends IntegrationTest {
public void testApplicationUserShallNotBeAbleToChangeItsOwnRoles() { public void testApplicationUserShallNotBeAbleToChangeItsOwnRoles() {
// Admin creates a new user with one role assigned // Admin creates a new user with one role assigned
Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
String password = "aA1qwerty56"; String password = "QwE!5rTy#9uP0";
String simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4); String simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4);
GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec);
PostUsersRequest createUserRequest = new PostUsersRequest().username(simpleUsername) 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")); 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);
});
}
} }
@@ -19,6 +19,8 @@
package org.apache.fineract.integrationtests.useradministration.users; package org.apache.fineract.integrationtests.useradministration.users;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath; import io.restassured.path.json.JsonPath;
@@ -44,7 +46,7 @@ public final class UserHelper {
private static final String READ_LOAN_PERMISSION = "READ_LOAN"; 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_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 static boolean SIMPLE_USER_CREATED = false;
private UserHelper() {} private UserHelper() {}
@@ -73,6 +75,13 @@ public final class UserHelper {
return GSON.fromJson(response, PostUsersResponse.class); 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, public static Object createUserForSelfService(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
int roleId, int staffId, int clientId, String attribute) { int roleId, int staffId, int clientId, String attribute) {
return Utils.performServerPost(requestSpec, responseSpec, CREATE_USER_URL, return Utils.performServerPost(requestSpec, responseSpec, CREATE_USER_URL,
@@ -161,6 +170,16 @@ public final class UserHelper {
return responseRequestSpec; 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) { private static String createSimpleRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
addRepaymentPermissionToRole(requestSpec, responseSpec, roleId); addRepaymentPermissionToRole(requestSpec, responseSpec, roleId);