diff --git a/fineract-provider/src/main/java/org/apache/fineract/batch/exception/ErrorHandler.java b/fineract-provider/src/main/java/org/apache/fineract/batch/exception/ErrorHandler.java index cb16b7435..342842c58 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/batch/exception/ErrorHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/batch/exception/ErrorHandler.java @@ -19,6 +19,7 @@ package org.apache.fineract.batch.exception; import com.google.gson.Gson; +import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse; import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; @@ -32,8 +33,10 @@ import org.apache.fineract.infrastructure.core.exceptionmapper.PlatformInternalS import org.apache.fineract.infrastructure.core.exceptionmapper.PlatformResourceNotFoundExceptionMapper; import org.apache.fineract.infrastructure.core.exceptionmapper.UnsupportedParameterExceptionMapper; import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper; +import org.apache.fineract.infrastructure.jobs.exception.LoanIdsHardLockedException; import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException; import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException; +import org.apache.http.HttpStatus; import org.springframework.dao.NonTransientDataAccessException; import org.springframework.transaction.TransactionException; @@ -49,7 +52,7 @@ import org.springframework.transaction.TransactionException; */ public class ErrorHandler extends RuntimeException { - private static Gson jsonHelper = GoogleGsonSerializerHelper.createGsonBuilder(true).create(); + private static final Gson jsonHelper = GoogleGsonSerializerHelper.createGsonBuilder(true).create(); /** * Sole Constructor @@ -69,63 +72,66 @@ public class ErrorHandler extends RuntimeException { if (exception instanceof AbstractPlatformDomainRuleException) { PlatformDomainRuleExceptionMapper mapper = new PlatformDomainRuleExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((AbstractPlatformDomainRuleException) exception).getEntity()); - return new ErrorInfo(500, 9999, errorBody); + return new ErrorInfo(HttpStatus.SC_INTERNAL_SERVER_ERROR, 9999, errorBody); } else if (exception instanceof AbstractPlatformResourceNotFoundException) { final PlatformResourceNotFoundExceptionMapper mapper = new PlatformResourceNotFoundExceptionMapper(); final String errorBody = jsonHelper .toJson(mapper.toResponse((AbstractPlatformResourceNotFoundException) exception).getEntity()); - return new ErrorInfo(404, 1001, errorBody); + return new ErrorInfo(HttpStatus.SC_NOT_FOUND, 1001, errorBody); } else if (exception instanceof UnsupportedParameterException) { final UnsupportedParameterExceptionMapper mapper = new UnsupportedParameterExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((UnsupportedParameterException) exception).getEntity()); - return new ErrorInfo(400, 2001, errorBody); + return new ErrorInfo(HttpStatus.SC_BAD_REQUEST, 2001, errorBody); } else if (exception instanceof PlatformApiDataValidationException) { final PlatformApiDataValidationExceptionMapper mapper = new PlatformApiDataValidationExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((PlatformApiDataValidationException) exception).getEntity()); - return new ErrorInfo(400, 2002, errorBody); + return new ErrorInfo(HttpStatus.SC_BAD_REQUEST, 2002, errorBody); } else if (exception instanceof PlatformDataIntegrityException) { final PlatformDataIntegrityExceptionMapper mapper = new PlatformDataIntegrityExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((PlatformDataIntegrityException) exception).getEntity()); - return new ErrorInfo(403, 3001, errorBody); + return new ErrorInfo(HttpStatus.SC_FORBIDDEN, 3001, errorBody); } else if (exception instanceof LinkedAccountRequiredException) { final PlatformDomainRuleExceptionMapper mapper = new PlatformDomainRuleExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((LinkedAccountRequiredException) exception).getEntity()); - return new ErrorInfo(403, 3002, errorBody); + return new ErrorInfo(HttpStatus.SC_FORBIDDEN, 3002, errorBody); } else if (exception instanceof MultiDisbursementDataRequiredException) { final PlatformDomainRuleExceptionMapper mapper = new PlatformDomainRuleExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((MultiDisbursementDataRequiredException) exception).getEntity()); - return new ErrorInfo(403, 3003, errorBody); + return new ErrorInfo(HttpStatus.SC_FORBIDDEN, 3003, errorBody); } else if (exception instanceof TransactionException) { - return new ErrorInfo(400, 4001, "{\"Exception\": " + exception.getMessage() + "}"); + return new ErrorInfo(HttpStatus.SC_BAD_REQUEST, 4001, "{\"Exception\": " + exception.getMessage() + "}"); } else if (exception instanceof PlatformInternalServerException) { final PlatformInternalServerExceptionMapper mapper = new PlatformInternalServerExceptionMapper(); final String errorBody = jsonHelper.toJson(mapper.toResponse((PlatformInternalServerException) exception).getEntity()); - return new ErrorInfo(500, 5001, errorBody); + return new ErrorInfo(HttpStatus.SC_INTERNAL_SERVER_ERROR, 5001, errorBody); } else if (exception instanceof NonTransientDataAccessException) { - return new ErrorInfo(400, 4001, "{\"Exception\": " + exception.getMessage() + "}"); + return new ErrorInfo(HttpStatus.SC_BAD_REQUEST, 4001, "{\"Exception\": " + exception.getMessage() + "}"); + } else if (exception instanceof LoanIdsHardLockedException e) { + String message = ApiGlobalErrorResponse.loanIsLocked(e.getLoanIdFromRequest()).toJson(); + return new ErrorInfo(HttpStatus.SC_CONFLICT, 4090, message); } - return new ErrorInfo(500, 9999, "{\"Exception\": " + exception.toString() + "}"); + return new ErrorInfo(HttpStatus.SC_INTERNAL_SERVER_ERROR, 9999, "{\"Exception\": " + exception.toString() + "}"); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/LoanIdsHardLockedException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/LoanIdsHardLockedException.java new file mode 100644 index 000000000..8a6d51b0e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/exception/LoanIdsHardLockedException.java @@ -0,0 +1,29 @@ +/** + * 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. + */ +package org.apache.fineract.infrastructure.jobs.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class LoanIdsHardLockedException extends RuntimeException { + + private final Long loanIdFromRequest; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java index 02135d9f2..1df21bd9e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilter.java @@ -31,7 +31,6 @@ import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import lombok.Getter; import lombok.RequiredArgsConstructor; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -45,6 +44,7 @@ import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse; import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.filters.BatchRequestPreprocessor; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; +import org.apache.fineract.infrastructure.jobs.exception.LoanIdsHardLockedException; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository; import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; @@ -86,13 +86,6 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchReque private final PlatformTransactionManager transactionManager; - @RequiredArgsConstructor - @Getter - private static class LoanIdsHardLockedException extends RuntimeException { - - private final Long loanIdFromRequest; - } - private static class Reject { private final String message; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java index 3e55560c3..39789ddbb 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java @@ -32,6 +32,7 @@ import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.time.LocalDate; import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -51,6 +52,7 @@ import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.charges.ChargesHelper; +import org.apache.fineract.integrationtests.common.loans.LoanAccountLockHelper; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; @@ -59,6 +61,7 @@ import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper; import org.apache.fineract.integrationtests.common.savings.SavingsStatusChecker; import org.apache.fineract.integrationtests.common.system.CodeHelper; import org.apache.fineract.integrationtests.common.system.DatatableHelper; +import org.apache.fineract.integrationtests.useradministration.users.UserHelper; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.http.HttpStatus; import org.junit.jupiter.api.Assertions; @@ -2262,6 +2265,87 @@ public class BatchApiTest { Assertions.assertEquals("true", changes.get("fraud").getAsString()); } + /** + * Tests that a loan is hard locked and if a repayment triggered in as a batch request, it returns the proper error + * + * @see org.apache.fineract.batch.command.internal.ModifyLoanApplicationByExternalIdCommandStrategy + */ + @Test + public void shoulRetrieveTheProperErrorDuringLockedLoan() { + ResponseSpecification responseSpec = new ResponseSpecBuilder().expectStatusCode(202).build(); + LoanAccountLockHelper loanAccountLockHelper = new LoanAccountLockHelper(this.requestSpec, responseSpec); + final String loanProductJSON = new LoanProductTestBuilder() // + .withPrincipal("1000.00") // + .withNumberOfRepayments("24") // + .withRepaymentAfterEvery("1") // + .withRepaymentTypeAsMonth() // + .withinterestRatePerPeriod("2") // + .withInterestRateFrequencyTypeAsMonths() // + .withAmortizationTypeAsEqualPrincipalPayment() // + .withInterestTypeAsDecliningBalance() // + .currencyDetails("0", "100").build(null); + + final Long applyLoanRequestId = RandomUtils.nextLong(100, 1000); + final Long approveLoanRequestId = applyLoanRequestId + 1; + final Long disburseLoanRequestId = approveLoanRequestId + 1; + final Long getLoanRequestId = disburseLoanRequestId + 1; + + // Create product + final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON); + + // Create client + final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId); + + final BatchRequest applyLoanRequest = BatchHelper.applyLoanRequestWithClientId(applyLoanRequestId, clientId, productId); + + final BatchRequest approveLoanRequest = BatchHelper.transistionLoanStateByExternalId(approveLoanRequestId, applyLoanRequestId, + LocalDate.now(ZoneId.systemDefault()).minusDays(10), "approve"); + + final BatchRequest disburseLoanRequest = BatchHelper.transistionLoanStateByExternalId(disburseLoanRequestId, approveLoanRequestId, + LocalDate.now(ZoneId.systemDefault()).minusDays(8), "disburse"); + + final BatchRequest getLoanRequest = BatchHelper.getLoanByExternalIdRequest(getLoanRequestId, approveLoanRequestId, + "associations=all"); + + // Create batch requests list + final List batchRequests = Arrays.asList(applyLoanRequest, approveLoanRequest, disburseLoanRequest, getLoanRequest); + + final String jsonifiedRequest = BatchHelper.toJsonString(batchRequests); + + final List responses = BatchHelper.postBatchRequestsWithoutEnclosingTransaction(this.requestSpec, this.responseSpec, + jsonifiedRequest); + + Assertions.assertEquals(HttpStatus.SC_OK, responses.get(0).getStatusCode(), "Verify Status Code 200 for Apply Loan"); + Assertions.assertEquals(HttpStatus.SC_OK, responses.get(1).getStatusCode(), "Verify Status Code 200 for Approve Loan"); + Assertions.assertEquals(HttpStatus.SC_OK, responses.get(2).getStatusCode(), "Verify Status Code 200 for Disburse Loan"); + Assertions.assertEquals(HttpStatus.SC_OK, responses.get(3).getStatusCode(), "Verify Status Code 200 for Get Loan"); + + final Long loanId = new FromJsonHelper().parse(responses.get(2).getBody()).getAsJsonObject().get("resourceId").getAsLong(); + + loanAccountLockHelper.placeSoftLockOnLoanAccount(loanId.intValue(), "LOAN_COB_CHUNK_PROCESSING"); + + RequestSpecification requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(this.requestSpec, this.responseSpec); + + // Create a repayment Request + final BatchRequest br = new BatchRequest(); + + br.setRequestId(1L); + br.setRelativeUrl(String.format("loans/" + loanId + "/transactions?command=repayment")); + br.setMethod("POST"); + String dateString = LocalDate.now(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("dd MMMM yyyy")); + br.setBody(String.format( + "{\"locale\": \"en\", \"dateFormat\": \"dd MMMM yyyy\", " + "\"transactionDate\": \"%s\", \"transactionAmount\": \"500\"}", + dateString)); + + final String jsonifiedRepaymentRequest = BatchHelper.toJsonString(List.of(br)); + + final List repaymentResponse = BatchHelper.postBatchRequestsWithoutEnclosingTransaction(requestSpec, + this.responseSpec, jsonifiedRepaymentRequest); + + Assertions.assertEquals(HttpStatus.SC_CONFLICT, repaymentResponse.get(0).getStatusCode(), "Verify Status Code 409 for Locked Loan"); + } + /** * Delete datatable * diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java index 41cbebee5..bfd709ff6 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java @@ -40,18 +40,14 @@ import org.apache.fineract.client.models.GetDelinquencyBucketsResponse; import org.apache.fineract.client.models.GetDelinquencyRangesResponse; import org.apache.fineract.client.models.GetDelinquencyTagHistoryResponse; import org.apache.fineract.client.models.GetLoansLoanIdResponse; -import org.apache.fineract.client.models.GetOfficesResponse; import org.apache.fineract.client.models.PostDelinquencyBucketResponse; import org.apache.fineract.client.models.PostDelinquencyRangeResponse; -import org.apache.fineract.client.models.PostUsersRequest; -import org.apache.fineract.client.models.PostUsersResponse; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; 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.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; -import org.apache.fineract.integrationtests.common.OfficeHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.charges.ChargesHelper; import org.apache.fineract.integrationtests.common.loans.LoanAccountLockHelper; @@ -62,7 +58,6 @@ import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtens import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; import org.apache.fineract.integrationtests.common.products.DelinquencyRangesHelper; -import org.apache.fineract.integrationtests.useradministration.roles.RolesHelper; import org.apache.fineract.integrationtests.useradministration.users.UserHelper; import org.apache.http.HttpStatus; import org.junit.jupiter.api.Assertions; @@ -74,9 +69,6 @@ import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(LoanTestLifecycleExtension.class) public class InlineLoanCOBTest { - private static final String REPAYMENT_LOAN_PERMISSION = "REPAYMENT_LOAN"; - private static final String READ_LOAN_PERMISSION = "READ_LOAN"; - private ResponseSpecification responseSpec; private RequestSpecification requestSpec; private InlineLoanCOBHelper inlineLoanCOBHelper; @@ -290,7 +282,7 @@ public class InlineLoanCOBTest { BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10)); - createNewSimpleUserWithoutBypassPermission(); + requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec); loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING"); loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); @@ -349,7 +341,7 @@ public class InlineLoanCOBTest { BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10)); - createNewSimpleUserWithoutBypassPermission(); + requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec); loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); loanTransactionHelper.makeRepayment("10 March 2020", 10.0f, loanID); @@ -406,7 +398,7 @@ public class InlineLoanCOBTest { BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10)); - createNewSimpleUserWithoutBypassPermission(); + requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec); loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING"); loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); @@ -443,37 +435,6 @@ public class InlineLoanCOBTest { assertEquals("Size of the loan IDs list cannot be over 1000", responseUserMessage); } - private void createNewSimpleUserWithoutBypassPermission() { - 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 simpleRoleId = createSimpleRole(); - 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) - .roles(List.of(simpleRoleId)).officeId(headOffice.getId()); - - PostUsersResponse userCreationResponse = UserHelper.createUser(requestSpec, responseSpec, createUserRequest); - Assertions.assertNotNull(userCreationResponse.getResourceId()); - - requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, password)); - responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - } - - private String createSimpleRole() { - Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); - addRepaymentPermissionToRole(roleId); - return roleId.toString(); - } - - private void addRepaymentPermissionToRole(Integer roleId) { - HashMap permissionMap = new HashMap<>(); - permissionMap.put(REPAYMENT_LOAN_PERMISSION, true); - permissionMap.put(READ_LOAN_PERMISSION, true); - RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap); - } - private Integer createLoanProduct(final String chargeId) { final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("15,000.00").withNumberOfRepayments("4") .withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("1") 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 316d0f317..67ae40926 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,15 +19,20 @@ package org.apache.fineract.integrationtests.useradministration.users; import com.google.gson.Gson; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.http.ContentType; import io.restassured.path.json.JsonPath; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.util.HashMap; import java.util.List; +import org.apache.fineract.client.models.GetOfficesResponse; import org.apache.fineract.client.models.PostUsersRequest; import org.apache.fineract.client.models.PostUsersResponse; import org.apache.fineract.client.util.JSON; +import org.apache.fineract.integrationtests.common.OfficeHelper; import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.useradministration.roles.RolesHelper; import org.junit.jupiter.api.Assertions; public final class UserHelper { @@ -35,6 +40,11 @@ public final class UserHelper { private static final String CREATE_USER_URL = "/fineract-provider/api/v1/users?" + Utils.TENANT_IDENTIFIER; private static final String USER_URL = "/fineract-provider/api/v1/users"; private static final Gson GSON = new JSON().getGson(); + private static final String REPAYMENT_LOAN_PERMISSION = "REPAYMENT_LOAN"; + private static final String READ_LOAN_PERMISSION = "READ_LOAN"; + + private static boolean simpleUserCreated = false; + private static String simpleUsername; private UserHelper() {} @@ -128,4 +138,40 @@ public final class UserHelper { private static String createRoleOperationURL(final Integer userId) { return USER_URL + "/" + userId + "?" + Utils.TENANT_IDENTIFIER; } + + public static RequestSpecification getSimpleUserWithoutBypassPermission(final RequestSpecification requestSpec, + final ResponseSpecification responseSpec) { + String password = "aA1qwerty56"; + if (!simpleUserCreated) { + GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(requestSpec, responseSpec); + simpleUsername = Utils.uniqueRandomStringGenerator("NotificationUser", 4); + String simpleRoleId = createSimpleRole(requestSpec, responseSpec); + PostUsersRequest createUserRequest = new PostUsersRequest().username(simpleUsername) + .firstname(Utils.randomStringGenerator("NotificationFN", 4)).lastname(Utils.randomStringGenerator("NotificationLN", 4)) + .email("whatever@mifos.org").password(password).repeatPassword(password).sendPasswordToEmail(false) + .roles(List.of(simpleRoleId)).officeId(headOffice.getId()); + + PostUsersResponse userCreationResponse = UserHelper.createUser(requestSpec, responseSpec, createUserRequest); + Assertions.assertNotNull(userCreationResponse.getResourceId()); + simpleUserCreated = true; + } + RequestSpecification responseRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); + responseRequestSpec.header("Authorization", + "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(simpleUsername, password)); + return responseRequestSpec; + } + + private static String createSimpleRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); + addRepaymentPermissionToRole(requestSpec, responseSpec, roleId); + return roleId.toString(); + } + + private static void addRepaymentPermissionToRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + Integer roleId) { + HashMap permissionMap = new HashMap<>(); + permissionMap.put(REPAYMENT_LOAN_PERMISSION, true); + permissionMap.put(READ_LOAN_PERMISSION, true); + RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap); + } }