FINERACT-1977: 4-eye-principle, maker-checker permission

This commit is contained in:
jmarta
2024-01-11 11:46:32 +01:00
committed by Adam Saghy
parent 2fe1b0e7d3
commit 16eac933d6
69 changed files with 887 additions and 359 deletions
@@ -2153,12 +2153,7 @@ public class BatchApiTest {
LOG.info("Batch Response : {}", new Gson().toJson(responseOfQueryAndUpdateDatatableBatch));
final BatchResponse queryResponse = responseOfQueryAndUpdateDatatableBatch.get(0);
Assertions.assertEquals(1L, queryResponse.getRequestId());
Assertions.assertEquals(HttpStatus.SC_OK, queryResponse.getStatusCode(), "Verify Status Code 200 for query datatable entry");
final BatchResponse updateResponse = responseOfQueryAndUpdateDatatableBatch.get(1);
final BatchResponse updateResponse = responseOfQueryAndUpdateDatatableBatch.get(0);
Assertions.assertEquals(2L, updateResponse.getRequestId());
Assertions.assertEquals(HttpStatus.SC_BAD_REQUEST, updateResponse.getStatusCode(),
@@ -21,6 +21,7 @@ package org.apache.fineract.integrationtests;
import static org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.PAUSE;
import static org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.RESUME;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -109,8 +110,10 @@ public class DelinquencyBucketsIntegrationTest {
// then
assertNotNull(delinquencyRangeResponse01);
assertNotNull(ranges);
assertEquals(1, ranges.get(0).getMinimumAgeDays(), "Expected Min Age Days to 1");
assertEquals(3, ranges.get(0).getMaximumAgeDays(), "Expected Max Age Days to 3");
assertFalse(ranges.isEmpty());
GetDelinquencyRangesResponse range = ranges.get(ranges.size() - 1);
assertEquals(1, range.getMinimumAgeDays(), "Expected Min Age Days to 1");
assertEquals(3, range.getMaximumAgeDays(), "Expected Max Age Days to 3");
}
@Test
@@ -19,22 +19,25 @@
package org.apache.fineract.integrationtests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ResponseBody;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.fineract.cob.data.BusinessStep;
import org.apache.fineract.cob.data.JobBusinessStepConfigData;
import org.apache.fineract.infrastructure.core.exception.AbstractIdempotentCommandException;
import org.apache.fineract.integrationtests.common.IdempotencyHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -70,9 +73,9 @@ public class IdempotencyTest {
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
Response responseSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
Assertions.assertEquals(response.getBody().asString(), responseSecond.getBody().asString());
Assertions.assertNull(response.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertNotNull(responseSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertEquals(response.getBody().asString(), responseSecond.getBody().asString());
assertNull(response.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertNotNull(responseSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
idempotencyKeyHeader = UUID.randomUUID().toString();
@@ -89,9 +92,9 @@ public class IdempotencyTest {
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
Response updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
Assertions.assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
newStepConfig = IdempotencyHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, LOAN_JOB_NAME);
applyChargeStep = newStepConfig.getBusinessSteps().stream()
@@ -109,9 +112,9 @@ public class IdempotencyTest {
updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
Assertions.assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
newStepConfig = IdempotencyHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, LOAN_JOB_NAME);
applyChargeStep = newStepConfig.getBusinessSteps().stream()
@@ -126,14 +129,14 @@ public class IdempotencyTest {
updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
IdempotencyHelper.toJsonString(originalStepConfig.getBusinessSteps()), idempotencyKeyHeader);
Assertions.assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
}
@Test
public void shoudTheSecondRequestWithSameIdempotencyKeyWillFailureToo() {
public void shouldTheSecondRequestWithSameIdempotencyKeyWillFailureToo() {
ResponseSpecification responseSpecForError = new ResponseSpecBuilder().expectStatusCode(400).build();
List<BusinessStep> requestBody = new ArrayList<>();
String idempotencyKey = UUID.randomUUID().toString();
@@ -141,13 +144,14 @@ public class IdempotencyTest {
Response response1 = IdempotencyHelper.updateBusinessStepOrderWithError(requestSpec, responseSpecForError, LOAN_JOB_NAME,
IdempotencyHelper.toJsonString(requestBody), idempotencyKey);
Assertions.assertNull(response1.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
String originalBody = response1.getBody().asString();
assertNull(response1.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
ResponseBody body1 = response1.getBody();
assertNotNull(body1);
Response response2 = IdempotencyHelper.updateBusinessStepOrderWithError(requestSpec, responseSpecForError, LOAN_JOB_NAME,
IdempotencyHelper.toJsonString(requestBody), idempotencyKey);
Assertions.assertNotNull(response2.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
Assertions.assertEquals(originalBody, response2.getBody().asString());
assertNotNull(response2.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
assertEquals((Map) body1.jsonPath().get(""), response2.getBody().jsonPath().get(""));
}
private BusinessStep getBusinessSteps(Long order, String stepName) {
@@ -181,8 +181,8 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.00)).locale("en"));
final float feePortion = 50.0f;
final float penaltyPortion = 100.0f;
final double feePortion = 50.0d;
final double penaltyPortion = 100.0d;
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateWithAccountTransferJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
@@ -209,8 +209,8 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
assertEquals(feePortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue());
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
assertEquals(400.0f, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
assertEquals(400.0f, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
assertEquals(400.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
assertEquals(400.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
assertEquals(LocalDate.of(2023, 1, 16), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
scheduleJobHelper.executeAndAwaitJob(jobName);
@@ -218,11 +218,11 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
loanDetails = loanTransactionHelper.getLoanDetails((long) loanId);
assertEquals(5, loanDetails.getRepaymentSchedule().getPeriods().size());
assertEquals(feePortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesDue());
assertEquals(0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
assertEquals(0.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue());
assertEquals(0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
assertEquals(400, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
assertEquals(250, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
assertEquals(0.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
assertEquals(400.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
assertEquals(250.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
assertEquals(LocalDate.of(2023, 1, 16), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
} finally {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
@@ -18,17 +18,31 @@
*/
package org.apache.fineract.integrationtests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.util.ArrayList;
import org.apache.fineract.client.models.GetMakerCheckerResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.client.models.GlobalConfigurationPropertyData;
import org.apache.fineract.client.models.PutPermissionsRequest;
import org.apache.fineract.integrationtests.common.AuditHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.commands.MakercheckersHelper;
import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
import org.apache.fineract.integrationtests.useradministration.roles.RolesHelper;
import org.apache.fineract.integrationtests.useradministration.users.UserHelper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -38,6 +52,12 @@ public class MakercheckerTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private MakercheckersHelper makercheckersHelper;
private RolesHelper rolesHelper;
private AuditHelper auditHelper;
private SavingsProductHelper savingsProductHelper;
private SavingsAccountHelper savingsAccountHelper;
private static final String START_DATE_STRING = "03 June 2023";
private static final String TRANSACTION_DATE_STRING = "05 June 2023";
@BeforeEach
public void setup() {
@@ -46,14 +66,151 @@ public class MakercheckerTest {
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.makercheckersHelper = new MakercheckersHelper(this.requestSpec, this.responseSpec);
this.rolesHelper = new RolesHelper();
this.auditHelper = new AuditHelper(requestSpec, responseSpec);
this.savingsProductHelper = new SavingsProductHelper();
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
}
@Test
public void testMakerchekerInboxList() {
public void testMakercheckerInboxList() {
// given
// when
final ArrayList<GetMakerCheckerResponse> makerCheckerList = this.makercheckersHelper.getMakerCheckerList();
List<Map<String, Object>> makerCheckerList = this.makercheckersHelper.getMakerCheckerList(null);
assertNotNull(makerCheckerList);
}
@Test
public void testMakerCheckerOn() {
GlobalConfigurationPropertyData mcConfig = GlobalConfigurationHelper.getGlobalConfigurationByName(requestSpec, responseSpec,
"maker-checker");
Long mcConfigId = mcConfig.getId();
boolean mcConfigUpdate = false;
if (!Boolean.TRUE.equals(mcConfig.getEnabled())) {
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, mcConfigId, true);
mcConfigUpdate = true;
}
GlobalConfigurationPropertyData sameMcConfig = GlobalConfigurationHelper.getGlobalConfigurationByName(requestSpec, responseSpec,
"enable-same-maker-checker");
Long sameMcConfigId = mcConfig.getId();
boolean sameMcConfigUpdate = false;
if (Boolean.TRUE.equals(sameMcConfig.getEnabled())) {
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, sameMcConfigId, false);
sameMcConfigUpdate = true;
}
try {
// client permission - maker-checker disabled
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("CREATE_CLIENT", false);
rolesHelper.updatePermissions(putPermissionsRequest);
putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("ACTIVATE_CLIENT", false);
rolesHelper.updatePermissions(putPermissionsRequest);
Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
Map<String, Boolean> permissionMap = Map.of("CREATE_CLIENT", true, "CREATE_CLIENT_CHECKER", true, "ACTIVATE_CLIENT", true,
"ACTIVATE_CLIENT_CHECKER", true, "WITHDRAWAL_SAVINGSACCOUNT", true, "WITHDRAWAL_SAVINGSACCOUNT_CHECKER", true);
RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap);
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
// create maker user
String maker = Utils.uniqueRandomStringGenerator("user", 8);
final Integer makerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker,
"P4ssw0rd", "resourceId");
// create client - maker-checker disabled
RequestSpecification makerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker, "P4ssw0rd"));
Integer clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId);
final Integer savingsId = createApproveActivateSavingsAccountDailyPosting(clientId, START_DATE_STRING);
assertNotNull(savingsId);
Integer transactionId = (Integer) savingsAccountHelper.depositToSavingsAccount(savingsId, "1000", TRANSACTION_DATE_STRING,
CommonConstants.RESPONSE_RESOURCE_ID);
assertNotNull(transactionId);
// client and saving permission - maker-checker enabled
putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("ACTIVATE_CLIENT", true);
rolesHelper.updatePermissions(putPermissionsRequest);
putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("WITHDRAWAL_SAVINGSACCOUNT", true);
rolesHelper.updatePermissions(putPermissionsRequest);
// create client - maker-checker enabled
clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
assertNull(clientId, "Client is created on the server");
List<Map<String, Object>> auditDetails = makercheckersHelper
.getMakerCheckerList(Map.of("actionName", "CREATE", "entityName", "CLIENT", "makerId", makerUserId.toString()));
assertEquals(1, auditDetails.size(), "More than one command exists");
Long clientCommandId = ((Double) auditDetails.get(0).get("id")).longValue();
// savings withdrawal - maker-checker enabled
SavingsAccountHelper makerSavingsHelper = new SavingsAccountHelper(makerRequestSpec, this.responseSpec);
Integer withdrawalId = (Integer) makerSavingsHelper.withdrawalFromSavingsAccount(savingsId, "100", TRANSACTION_DATE_STRING,
CommonConstants.RESPONSE_RESOURCE_ID);
assertNull(withdrawalId, "Withdrawal performed on the server");
auditDetails = makercheckersHelper.getMakerCheckerList(
Map.of("actionName", "WITHDRAWAL", "entityName", "SAVINGSACCOUNT", "makerId", makerUserId.toString()));
assertEquals(1, auditDetails.size(), "More than one command exists");
Long savingCommandId = ((Double) auditDetails.get(0).get("id")).longValue();
// check by the same user should fail
ResponseSpecification failedResponseSpec = new ResponseSpecBuilder().expectStatusCode(400).build();
MakercheckersHelper.approveMakerCheckerEntry(makerRequestSpec, failedResponseSpec, clientCommandId);
MakercheckersHelper.approveMakerCheckerEntry(makerRequestSpec, failedResponseSpec, savingCommandId);
// create checker user
String checker = Utils.uniqueRandomStringGenerator("user", 8);
final Integer checkerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, checker,
"P4ssw0rd", "resourceId");
RequestSpecification checkerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(checker, "P4ssw0rd"));
// check by another checker user should succeed
HashMap<?, ?> response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, clientCommandId);
assertNotNull(response);
clientId = (Integer) response.get("clientId");
assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientId);
response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, savingCommandId);
assertNotNull(response);
withdrawalId = (Integer) response.get("resourceId");
assertNotNull(withdrawalId);
// add checker superuser permission - actions are performed in one step
permissionMap = Map.of("CHECKER_SUPER_USER", true);
RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap);
clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
assertNotNull(clientId);
ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId);
withdrawalId = (Integer) makerSavingsHelper.withdrawalFromSavingsAccount(savingsId, "100", TRANSACTION_DATE_STRING,
CommonConstants.RESPONSE_RESOURCE_ID);
assertNotNull(withdrawalId);
} finally {
if (mcConfigUpdate) {
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, mcConfigId, false);
}
if (sameMcConfigUpdate) {
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, sameMcConfigId, true);
}
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("WITHDRAWAL_SAVINGSACCOUNT",
false);
rolesHelper.updatePermissions(putPermissionsRequest);
}
}
private Integer createSavingsProductDailyPosting() {
final String savingsProductJSON = this.savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
.withInterestPostingPeriodTypeAsDaily().withInterestCalculationPeriodTypeAsDailyBalance().build();
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
}
private Integer createApproveActivateSavingsAccountDailyPosting(final Integer clientID, final String startDate) {
final Integer savingsProductID = createSavingsProductDailyPosting();
assertNotNull(savingsProductID);
return savingsAccountHelper.createApproveActivateSavingsAccount(clientID, savingsProductID, startDate);
}
}
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.integrationtests;
import static org.apache.fineract.integrationtests.common.CommonConstants.RESPONSE_RESOURCE_ID;
import static org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper.PAYMENT_TYPE_ID;
import static org.apache.fineract.integrationtests.common.system.DatatableHelper.addDatatableColumn;
import static org.apache.http.HttpStatus.SC_CONFLICT;
@@ -60,7 +61,6 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.integrationtests.common.BatchHelper;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
@@ -118,7 +118,7 @@ public class SavingsAccountTransactionTest {
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDateString);
assertNotNull(clientID);
final Integer savingsId = createSavingsAccountDailyPosting(clientID, startDateString);
final Integer savingsId = createApproveActivateSavingsAccountDailyPosting(clientID, startDateString);
assertNotNull(savingsId);
performSavingsTransaction(savingsId, "100", depositDate, true);
@@ -176,7 +176,7 @@ public class SavingsAccountTransactionTest {
// creating datatable for client entity
final HashMap<String, Object> columnMap = new HashMap<>();
String datatableName = Utils.uniqueRandomStringGenerator("savings_transaction" + "_", 5).toLowerCase();
String datatableName = Utils.uniqueRandomStringGenerator("dt_savings_transaction_", 5).toLowerCase();
columnMap.put("datatableName", datatableName);
columnMap.put("apptableName", "m_savings_account_transaction");
columnMap.put("multiRow", false);
@@ -284,10 +284,9 @@ public class SavingsAccountTransactionTest {
private void performSavingsTransaction(Integer savingsId, String amount, LocalDate transactionDate, boolean isDeposit) {
String transactionType = isDeposit ? "Deposit" : "Withdrawal";
Integer transactionId = isDeposit
? (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, amount, depositDateString,
CommonConstants.RESPONSE_RESOURCE_ID)
? (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, amount, depositDateString, RESPONSE_RESOURCE_ID)
: (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, amount, withdrawDateString,
CommonConstants.RESPONSE_RESOURCE_ID);
RESPONSE_RESOURCE_ID);
assertNotNull(transactionId);
@@ -311,17 +310,10 @@ public class SavingsAccountTransactionTest {
return extractedDate;
}
private Integer createSavingsAccountDailyPosting(final Integer clientID, final String startDate) {
private Integer createApproveActivateSavingsAccountDailyPosting(final Integer clientID, final String startDate) {
final Integer savingsProductID = createSavingsProductDailyPosting();
assertNotNull(savingsProductID);
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID, savingsProductID,
ACCOUNT_TYPE_INDIVIDUAL, startDate);
assertNotNull(savingsId);
HashMap savingsStatusHashMap = this.savingsAccountHelper.approveSavingsOnDate(savingsId, startDate);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
savingsStatusHashMap = this.savingsAccountHelper.activateSavingsAccount(savingsId, startDate);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
return savingsId;
return savingsAccountHelper.createApproveActivateSavingsAccount(clientID, savingsProductID, startDate);
}
private Integer createSavingsProductDailyPosting() {
@@ -382,28 +374,31 @@ public class SavingsAccountTransactionTest {
final List<BatchResponse> responses = enclosingTransaction
? BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, json)
: BatchHelper.postBatchRequestsWithoutEnclosingTransaction(requestSpec, responseSpec, json);
assertNotNull(responses);
assertNotNull(responses, "Responses");
if (enclosingTransaction) {
Integer statusCode1 = responses.get(0).getStatusCode();
assertNotNull(statusCode1);
assertNotNull(statusCode1, "First enlosingTransaction response status code");
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1, "Status code: " + statusCode1);
if (SC_OK == statusCode1) {
assertEquals(4, responses.size());
assertEquals(4, responses.size(), "Response size for enlosingTransaction OK response");
Integer statusCode4 = responses.get(3).getStatusCode();
assertNotNull(statusCode4);
assertEquals(SC_OK, statusCode4);
assertNotNull(statusCode4, "Last enlosingTransaction OK response status code");
assertEquals(SC_OK, statusCode4, "Last enlosingTransaction OK response status code");
} else {
assertEquals(1, responses.size());
assertEquals(1, responses.size(), "Response size for enlosingTransaction failed response");
}
} else {
assertEquals(4, responses.size());
assertEquals(4, responses.size(), "Response size for without-enlosingTransaction response");
Integer statusCode1 = responses.get(0).getStatusCode();
assertNotNull(statusCode1);
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1, "Status code: " + statusCode1);
assertNotNull(statusCode1, "First without-enlosingTransaction response status code");
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1,
"First without-enlosingTransaction response status code: " + statusCode1);
Integer statusCode4 = responses.get(3).getStatusCode();
assertNotNull(statusCode4);
assertTrue(SC_OK == statusCode1 ? (SC_OK == statusCode4 || SC_CONFLICT == statusCode4)
: (SC_FORBIDDEN == statusCode4 || SC_CONFLICT == statusCode4), "Status code: " + statusCode4);
assertNotNull(statusCode4, "Last without-enlosingTransaction response status code");
assertTrue(
SC_OK == statusCode1 ? (SC_OK == statusCode4 || SC_CONFLICT == statusCode4)
: (SC_FORBIDDEN == statusCode4 || SC_CONFLICT == statusCode4),
"Last without-enlosingTransaction response status code: " + statusCode4);
}
} else {
String json = transactionData.getJson();
@@ -417,14 +412,14 @@ public class SavingsAccountTransactionTest {
}
private static boolean checkConcurrentResponse(String response) {
assertNotNull(response);
assertNotNull(response, "Single response");
JsonPath res = JsonPath.from(response);
String statusCode = res.get("httpStatusCode");
if (statusCode == null) {
assertNotNull(res.get(CommonConstants.RESPONSE_RESOURCE_ID));
assertNotNull(res.get(RESPONSE_RESOURCE_ID), "Single response " + RESPONSE_RESOURCE_ID);
return true;
}
assertEquals(String.valueOf(SC_CONFLICT), statusCode);
assertEquals(String.valueOf(SC_CONFLICT), statusCode, "Single response status code");
return false;
}
}
@@ -439,22 +434,22 @@ public class SavingsAccountTransactionTest {
RequestSpecification requestSpec = savingsHelper.getRequestSpec();
ResponseSpecification responseSpec = savingsHelper.getResponseSpec();
final List<BatchResponse> responses = BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, json);
assertNotNull(responses);
assertNotNull(responses, "Responses");
BatchResponse response1 = responses.get(0);
Integer statusCode = response1.getStatusCode();
String msg = Strings.nullToEmpty(response1.getBody());
assertNotNull(statusCode);
assertNotNull(statusCode, "First response status code");
assertTrue(
SC_OK == statusCode || SC_CONFLICT == statusCode
|| (SC_FORBIDDEN == statusCode && msg.contains("Cannot add or update a child row")),
"Status code: " + statusCode + ", message: " + msg);
if (SC_OK == statusCode) {
assertEquals(4, responses.size());
assertEquals(4, responses.size(), "Response size for OK response");
Integer statusCode4 = responses.get(3).getStatusCode();
assertNotNull(statusCode4);
assertEquals(SC_OK, statusCode4);
assertNotNull(statusCode4, "Last OK response status code");
assertEquals(SC_OK, statusCode4, "Last OK response status code");
} else {
assertEquals(1, responses.size());
assertEquals(1, responses.size(), "Response size for failed response");
}
}
@@ -20,6 +20,7 @@ package org.apache.fineract.integrationtests.common;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.google.gson.Gson;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.util.Collections;
@@ -27,6 +28,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import org.apache.fineract.client.util.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,13 +40,15 @@ import org.slf4j.LoggerFactory;
public class AuditHelper {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private static final Logger LOG = LoggerFactory.getLogger(AuditHelper.class);
private static final String AUDIT_BASE_URL = "/fineract-provider/api/v1/audits?" + Utils.TENANT_IDENTIFIER;
private static final String AUDITSEARCH_BASE_URL = "/fineract-provider/api/v1/audits/searchtemplate?" + Utils.TENANT_IDENTIFIER;
private static final Gson GSON = new JSON().getGson();
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
public AuditHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
this.requestSpec = requestSpec;
this.responseSpec = responseSpec;
@@ -119,8 +119,8 @@ public class GlobalConfigurationHelper {
ArrayList<HashMap> expectedGlobalConfigurations = getAllDefaultGlobalConfigurations();
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
Assertions.assertEquals(52, expectedGlobalConfigurations.size());
Assertions.assertEquals(52, actualGlobalConfigurations.size());
Assertions.assertEquals(53, expectedGlobalConfigurations.size());
Assertions.assertEquals(53, actualGlobalConfigurations.size());
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
@@ -571,9 +571,16 @@ public class GlobalConfigurationHelper {
assetExternalizationOfNonActiveLoans.put("value", 0);
assetExternalizationOfNonActiveLoans.put("enabled", true);
assetExternalizationOfNonActiveLoans.put("trapDoor", false);
assetExternalizationOfNonActiveLoans.put("string_value", "due-date");
defaults.add(assetExternalizationOfNonActiveLoans);
HashMap<String, Object> enableSameMakerChecker = new HashMap<>();
enableSameMakerChecker.put("id", 58);
enableSameMakerChecker.put("name", "enable-same-maker-checker");
enableSameMakerChecker.put("value", 0);
enableSameMakerChecker.put("enabled", false);
enableSameMakerChecker.put("trapDoor", false);
defaults.add(enableSameMakerChecker);
return defaults;
}
@@ -23,8 +23,9 @@ import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;
import java.util.ArrayList;
import org.apache.fineract.client.models.GetMakerCheckerResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.client.util.JSON;
import org.apache.fineract.integrationtests.common.Utils;
@@ -32,7 +33,7 @@ public class MakercheckersHelper {
private static final Gson GSON = new JSON().getGson();
private static final String MAKERCHECKER_URL = "/fineract-provider/api/v1/makercheckers?" + Utils.TENANT_IDENTIFIER;
private static final String MAKERCHECKER_URL = "/fineract-provider/api/v1/makercheckers";
private final RequestSpecification requestSpec;
private final ResponseSpecification responseSpec;
@@ -42,10 +43,25 @@ public class MakercheckersHelper {
this.responseSpec = responseSpec;
}
public ArrayList<GetMakerCheckerResponse> getMakerCheckerList() {
final String response = Utils.performServerGet(this.requestSpec, this.responseSpec, MAKERCHECKER_URL);
Type makerCheckerList = new TypeToken<ArrayList<GetMakerCheckerResponse>>() {}.getType();
public List<Map<String, Object>> getMakerCheckerList(Map<String, String> queryParams) {
StringBuilder url = new StringBuilder(MAKERCHECKER_URL).append("?").append(Utils.TENANT_IDENTIFIER);
if (queryParams != null) {
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
url.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
}
final String response = Utils.performServerGet(this.requestSpec, this.responseSpec, url.toString());
Type makerCheckerList = new TypeToken<List<Map<String, Object>>>() {}.getType();
return GSON.fromJson(response, makerCheckerList);
}
public void approveMakerCheckerEntry(Long auditId) {
approveMakerCheckerEntry(this.requestSpec, this.responseSpec, auditId);
}
public static HashMap<?, ?> approveMakerCheckerEntry(RequestSpecification requestSpec, ResponseSpecification responseSpec,
Long auditId) {
String url = MAKERCHECKER_URL + "/" + auditId + "?command=approve&" + Utils.TENANT_IDENTIFIER;
return Utils.performServerPost(requestSpec, responseSpec, url, "", "");
}
}
@@ -20,6 +20,7 @@ package org.apache.fineract.integrationtests.common.savings;
import static org.apache.fineract.integrationtests.common.Utils.DEFAULT_TENANT;
import static org.apache.fineract.integrationtests.common.Utils.TENANT_PARAM_NAME;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
@@ -174,6 +175,16 @@ public class SavingsAccountHelper extends IntegrationTest {
savingsApplicationJSON, responseAttribute);
}
public Integer createApproveActivateSavingsAccount(final Integer clientId, Integer savingsProductId, final String startDate) {
final Integer savingsId = applyForSavingsApplicationOnDate(clientId, savingsProductId, ACCOUNT_TYPE_INDIVIDUAL, startDate);
assertNotNull(savingsId);
HashMap savingsStatusHashMap = approveSavingsOnDate(savingsId, startDate);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
savingsStatusHashMap = activateSavingsAccount(savingsId, startDate);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
return savingsId;
}
public HashMap updateSavingsAccount(final Integer id, final Integer savingsProductID, final Integer savingsId,
final String accountType) {
final String savingsApplicationJSON = new SavingsApplicationTestBuilder() //
@@ -19,24 +19,36 @@
package org.apache.fineract.integrationtests.useradministration.roles;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.client.models.CommandProcessingResult;
import org.apache.fineract.client.models.PutPermissionsRequest;
import org.apache.fineract.client.util.JSON;
import org.apache.fineract.integrationtests.client.IntegrationTest;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.useradministration.data.PermissionData;
public final class RolesHelper {
public final class RolesHelper extends IntegrationTest {
public static final long SUPER_USER_ROLE_ID = 1L; // This is hardcoded into the initial Liquibase migration
private RolesHelper() {
public RolesHelper() {
}
private static final String CREATE_ROLE_URL = "/fineract-provider/api/v1/roles?" + Utils.TENANT_IDENTIFIER;
private static final String ROLE_URL = "/fineract-provider/api/v1/roles";
private static final String PERMISSIONS_URL = "/fineract-provider/api/v1/permissions";
private static final String DISABLE_ROLE_COMMAND = "disable";
private static final String ENABLE_ROLE_COMMAND = "enable";
private static final Gson GSON = new JSON().getGson();
public static Integer createRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
return Utils.performServerPost(requestSpec, responseSpec, CREATE_ROLE_URL, getTestCreateRoleAsJSON(), "resourceId");
}
@@ -70,13 +82,25 @@ public final class RolesHelper {
}
public static String addPermissionsToRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final Integer roleId, final HashMap<String, Boolean> permissionMap) {
final Integer roleId, final Map<String, Boolean> permissionMap) {
return Utils.performServerPut(requestSpec, responseSpec, ROLE_URL + "/" + roleId + "/permissions?" + Utils.TENANT_IDENTIFIER,
getAddPermissionsToRoleJSON(permissionMap));
}
private static String getAddPermissionsToRoleJSON(HashMap<String, Boolean> permissionMap) {
final HashMap<String, HashMap<String, Boolean>> map = new HashMap<>();
public static List<PermissionData> getPermissions(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
boolean makerCheckerable) {
String response = Utils.performServerGet(requestSpec, responseSpec,
PERMISSIONS_URL + "?" + makerCheckerable + "=" + makerCheckerable);
final Type listType = new TypeToken<List<PermissionData>>() {}.getType();
return GSON.fromJson(response, listType);
}
public CommandProcessingResult updatePermissions(PutPermissionsRequest request) {
return ok(fineract().permissions.updatePermissionsDetails(request));
}
private static String getAddPermissionsToRoleJSON(Map<String, Boolean> permissionMap) {
final HashMap<String, Map<String, Boolean>> map = new HashMap<>();
map.put("permissions", permissionMap);
return new Gson().toJson(map);
}
@@ -84,5 +108,4 @@ public final class RolesHelper {
private static String createRoleOperationURL(final String command, final Integer roleId) {
return ROLE_URL + "/" + roleId + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
}
}