Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.GET;
Expand Down Expand Up @@ -66,6 +69,7 @@ public class AuditsApiResource {
+ "\n" + "Example Requests:\n" + "\n" + "audits\n" + "\n" + "audits?fields=madeOnDate,maker,processingResult\n" + "\n"
+ "audits?makerDateTimeFrom=2013-03-25 08:00:00&makerDateTimeTo=2013-04-04 18:00:00\n" + "\n" + "audits?officeId=1\n" + "\n"
+ "audits?officeId=1&includeJson=true")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AuditsApiResourceSwagger.PageGetAuditsResponse.class)))
public String retrieveAuditEntries(@Context final UriInfo uriInfo, @BeanParam AuditRequest auditRequest,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 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.commands.api;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import org.apache.fineract.commands.data.AuditData;

final class AuditsApiResourceSwagger {

private AuditsApiResourceSwagger() {}

@Schema(description = "PageGetAuditsResponse")
public static final class PageGetAuditsResponse {

private PageGetAuditsResponse() {}

@Schema(example = "1")
public Integer totalFilteredRecords;
public List<AuditData> pageItems;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,23 @@ public void afterPropertiesSet() {
@Path("{loanId}/audit")
@Produces({ MediaType.APPLICATION_JSON })
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public AuditData getLoanAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId) {
public LoanAuditFieldsData getLoanAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId) {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("Fetching loan with {}", loanId);
log.warn(" ");
log.warn("------------------------------------------------------------");

final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
return new AuditData(loan.getCreatedBy().orElse(null), loan.getCreatedDate().orElse(null), loan.getLastModifiedBy().orElse(null),
loan.getLastModifiedDate().orElse(null));
return new LoanAuditFieldsData(loan.getCreatedBy().orElse(null), loan.getCreatedDate().orElse(null),
loan.getLastModifiedBy().orElse(null), loan.getLastModifiedDate().orElse(null));
}

@GET
@Path("{loanId}/transaction/{transactionId}/audit")
@Produces({ MediaType.APPLICATION_JSON })
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public AuditData getLoanTransactionAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId,
public LoanAuditFieldsData getLoanTransactionAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId,
@PathParam("transactionId") Long transactionId) {
log.warn("------------------------------------------------------------");
log.warn(" ");
Expand All @@ -97,7 +97,7 @@ public AuditData getLoanTransactionAuditFields(@Context final UriInfo uriInfo, @
log.warn("------------------------------------------------------------");

final LoanTransaction transaction = loanTransactionRepository.findById(transactionId).orElseThrow();
return new AuditData(transaction.getCreatedBy().orElse(null), transaction.getCreatedDate().orElse(null),
return new LoanAuditFieldsData(transaction.getCreatedBy().orElse(null), transaction.getCreatedDate().orElse(null),
transaction.getLastModifiedBy().orElse(null), transaction.getLastModifiedDate().orElse(null));
}

Expand Down Expand Up @@ -145,6 +145,6 @@ public LocalDate getMaxTransactionDateOfActiveLoans() {
return loanRepositoryWrapper.findMaxTransactionDateOfActiveLoans();
}

private record AuditData(Long createdBy, OffsetDateTime createdDate, Long lastModifiedBy, OffsetDateTime lastModifiedDate) {
private record LoanAuditFieldsData(Long createdBy, OffsetDateTime createdDate, Long lastModifiedBy, OffsetDateTime lastModifiedDate) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import io.restassured.specification.ResponseSpecification;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import org.apache.fineract.client.models.AuditData;
import org.apache.fineract.client.models.AuditSearchData;
import org.apache.fineract.integrationtests.common.AuditHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.OfficeHelper;
Expand All @@ -51,7 +51,6 @@ public class AuditIntegrationTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private ClientHelper clientHelper;
private AuditHelper auditHelper;
private SchedulerJobHelper schedulerJobHelper;
private static final SecureRandom rand = new SecureRandom();

Expand All @@ -65,7 +64,6 @@ public void setup() {
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.auditHelper = new AuditHelper(this.requestSpec, this.responseSpec);
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
this.schedulerJobHelper = new SchedulerJobHelper(this.requestSpec);
}
Expand All @@ -74,19 +72,17 @@ public void setup() {
public void testAuditSearchTemplate() {
// given
// when
LinkedHashMap auditSearchTemplate = this.auditHelper.getAuditSearchTemplate();
AuditSearchData auditSearchTemplate = AuditHelper.getAuditSearchTemplate();

// then
assertNotNull(auditSearchTemplate);
assertEquals(4, auditSearchTemplate.size()); // appUsers, actionNames, entityNames, processingResults
assertTrue(((List) auditSearchTemplate.get("actionNames")).size() > 0);
assertTrue(auditSearchTemplate.getActionNames().size() > 0);

// verify all command processing status enum values are present and use enum_value (not enum_message_property)
List<LinkedHashMap> statuses = (List<LinkedHashMap>) auditSearchTemplate.get("statuses");
assertNotNull(statuses);
assertEquals(6, statuses.size());
assertNotNull(auditSearchTemplate.getStatuses());
assertEquals(6, auditSearchTemplate.getStatuses().size());

List<String> statusValues = statuses.stream().map(r -> (String) r.get("processingResult"))
List<String> statusValues = auditSearchTemplate.getStatuses().stream().map(r -> r.getProcessingResult())
.collect(java.util.stream.Collectors.toList());

assertTrue(statusValues.contains("Invalid"));
Expand All @@ -101,44 +97,43 @@ public void testAuditSearchTemplate() {
* Here we Create/Update different Entities and verify an audit is generated for each action. This can be further
* extened with more entities and actions in similiar way.
*/
@SuppressWarnings("unchecked")
@Test
public void auditShouldbeCreated() {
// Audits recieved after all actions are performed.
List<HashMap<String, Object>> auditsRecieved;
List<AuditData> auditsRecieved;

// Audits recieved before any action is performed, needed in special
// cases eg: reactivate client, close client
List<HashMap<String, Object>> auditsRecievedInitial;
List<AuditData> auditsRecievedInitial;

// When Client is created: Count should be "1"
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);

auditsRecieved = auditHelper.getAuditDetails(clientId, "CREATE", "CLIENT");
auditHelper.verifyOneAuditOnly(auditsRecieved, clientId, "CREATE", "CLIENT");
auditsRecieved = AuditHelper.getAuditDetails(clientId, "CREATE", "CLIENT");
AuditHelper.verifyOneAuditOnly(auditsRecieved, clientId, "CREATE", "CLIENT");

// Performs multiple close and reactivate on client

for (int i = 0; i < 4; i++) {
// Close
auditsRecievedInitial = auditHelper.getAuditDetails(clientId, "CLOSE", "CLIENT");
auditsRecievedInitial = AuditHelper.getAuditDetails(clientId, "CLOSE", "CLIENT");
this.clientHelper.closeClient(clientId);
auditsRecieved = auditHelper.getAuditDetails(clientId, "CLOSE", "CLIENT");
auditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, clientId, "CLOSE", "CLIENT");
auditsRecieved = AuditHelper.getAuditDetails(clientId, "CLOSE", "CLIENT");
AuditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, clientId, "CLOSE", "CLIENT");

// Activate
auditsRecievedInitial = auditHelper.getAuditDetails(clientId, "REACTIVATE", "CLIENT");
auditsRecievedInitial = AuditHelper.getAuditDetails(clientId, "REACTIVATE", "CLIENT");
this.clientHelper.reactivateClient(clientId);
auditsRecieved = auditHelper.getAuditDetails(clientId, "REACTIVATE", "CLIENT");
auditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, clientId, "REACTIVATE", "CLIENT");
auditsRecieved = AuditHelper.getAuditDetails(clientId, "REACTIVATE", "CLIENT");
AuditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, clientId, "REACTIVATE", "CLIENT");
}

// When Office is created
OfficeHelper officeHelper = new OfficeHelper();
int officeId = officeHelper.createOffice(java.time.LocalDate.of(2020, 6, 22)).getResourceId().intValue();
auditsRecieved = auditHelper.getAuditDetails(officeId, "CREATE", "OFFICE");
auditHelper.verifyOneAuditOnly(auditsRecieved, officeId, "CREATE", "OFFICE");
auditsRecieved = AuditHelper.getAuditDetails(officeId, "CREATE", "OFFICE");
AuditHelper.verifyOneAuditOnly(auditsRecieved, officeId, "CREATE", "OFFICE");
}

@Test
Expand All @@ -159,7 +154,7 @@ public void checkAuditsWithLimitParam() {
for (int i = 0; i < 3; i++) {
// limit contains a number between 1-8
int limit = rand.nextInt(7) + 1;
auditHelper.verifyLimitParameterfor(limit);
AuditHelper.verifyLimitParameterfor(limit);
}
}

Expand All @@ -170,24 +165,23 @@ public void checkIfOrderBySupported() {
"madeOnDate", "id", "loanId", "actionName");

for (int i = 0; i < shouldBeSupportedFor.size(); i++) {
auditHelper.verifyOrderBysupported(shouldBeSupportedFor.get(i));
AuditHelper.verifyOrderBysupported(shouldBeSupportedFor.get(i));
}

}

@SuppressWarnings("unchecked")
@Test
public void executeSchedulerJobShouldCreateAuditEntry() {
// given
int jobId = schedulerJobHelper.getSchedulerJobIdByShortName("SA_AANF").intValue();
List<HashMap<String, Object>> auditsRecievedInitial = auditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER");
List<AuditData> auditsRecievedInitial = AuditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER");

// when
schedulerJobHelper.runSchedulerJob(jobId);

// then
List<HashMap<String, Object>> auditsRecieved = auditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER");
auditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, jobId, "EXECUTEJOB", "SCHEDULER");
List<AuditData> auditsRecieved = AuditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER");
AuditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, jobId, "EXECUTEJOB", "SCHEDULER");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.client.models.AuditData;
import org.apache.fineract.integrationtests.common.AuditHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.Utils;
Expand All @@ -36,7 +36,6 @@

public class IpTrackingIntegrationTest {

private AuditHelper auditHelper;
private static final String EXPECTED_LOCAL_IP = "127.0.0.1";
private RequestSpecification requestSpec;
private ResponseSpecification responseSpec;
Expand All @@ -50,7 +49,6 @@ public void setup() {
this.requestSpec.auth().basic("mifos", "password");
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.responseSpecForSearch = new ResponseSpecBuilder().expectStatusCode(200).build();
this.auditHelper = new AuditHelper(this.requestSpec, this.responseSpec);
}

@Test
Expand All @@ -61,10 +59,10 @@ public void capturesIpAddressWhenCreatingClient() throws Exception {
// given
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
List<HashMap<String, Object>> auditsRecieved = auditHelper.getAuditDetails(clientId, "CREATE", "CLIENT");
List<AuditData> auditsRecieved = AuditHelper.getAuditDetails(clientId, "CREATE", "CLIENT");

// when
String ip = auditsRecieved.get(0).get("ip").toString();
String ip = auditsRecieved.get(0).getIp();

assumeTrue(!ip.isEmpty(), "IP not arrived: skipping capture test when enabled");
// then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
import org.apache.fineract.client.models.PutPermissionsRequest;
import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants;
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.FineractClientHelper;
Expand All @@ -58,7 +57,6 @@ public class MakercheckerTest {
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";
Expand All @@ -73,7 +71,6 @@ public void setup() {
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);
this.globalConfigurationHelper = new GlobalConfigurationHelper();
Expand Down
Loading
Loading