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 @@ -131,8 +131,25 @@ private SQLBuilder getExtraCriteria(MakerCheckerRequest makerCheckerRequest) {
}
extraCriteria.addNonNullCriteria("aud.resource_id = ", makerCheckerRequest.getResourceId());
extraCriteria.addNonNullCriteria("aud.maker_id = ", makerCheckerRequest.getMakerId());
extraCriteria.addNonNullCriteria("aud.made_on_date >= ", makerCheckerRequest.getMakerDateTimeFrom());
extraCriteria.addNonNullCriteria("aud.made_on_date <= ", makerCheckerRequest.getMakerDateTimeTo());
if (StringUtils.isNotBlank(makerCheckerRequest.getUsername())) {
extraCriteria.addCriteria("mk.username like ", makerCheckerRequest.getUsername().trim() + "%");
}
if (makerCheckerRequest.getMakerDateTimeFrom() != null) {
extraCriteria.addSubOperation((SQLBuilder criteria) -> {
criteria.addNonNullCriteria("aud.made_on_date >= ", makerCheckerRequest.getMakerDateTimeFrom(),
SQLBuilder.WhereLogicalOperator.NONE);
criteria.addNonNullCriteria("aud.made_on_date_utc >= ", makerCheckerRequest.getMakerDateTimeFrom(),
SQLBuilder.WhereLogicalOperator.OR);
});
}
if (makerCheckerRequest.getMakerDateTimeTo() != null) {
extraCriteria.addSubOperation((SQLBuilder criteria) -> {
criteria.addNonNullCriteria("aud.made_on_date <= ", makerCheckerRequest.getMakerDateTimeTo(),
SQLBuilder.WhereLogicalOperator.NONE);
criteria.addNonNullCriteria("aud.made_on_date_utc <= ", makerCheckerRequest.getMakerDateTimeTo(),
SQLBuilder.WhereLogicalOperator.OR);
});
}
extraCriteria.addNonNullCriteria("aud.office_id = ", makerCheckerRequest.getOfficeId());
extraCriteria.addNonNullCriteria("aud.group_id = ", makerCheckerRequest.getGroupId());
extraCriteria.addNonNullCriteria("aud.client_id = ", makerCheckerRequest.getClientId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@
import jakarta.ws.rs.QueryParam;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.service.DateUtils;

@Setter
Expand All @@ -44,6 +50,8 @@ public class MakerCheckerRequest implements Serializable {
private Long resourceId;
@QueryParam("makerId")
private Long makerId;
@QueryParam("username")
private String username;
@QueryParam("makerDateTimeFrom")
private String makerDateTimeFrom;
@QueryParam("makerDateTimeTo")
Expand All @@ -64,10 +72,28 @@ public class MakerCheckerRequest implements Serializable {
private String locale;

public OffsetDateTime getMakerDateTimeFrom() {
return DateUtils.convertDateTimeStringToOffsetDateTime(makerDateTimeFrom, dateFormat, locale, LocalTime.MIN);
OffsetDateTime parsed = tryParseDayMonthYear(makerDateTimeFrom, LocalTime.MIN);
return parsed != null ? parsed
: DateUtils.convertDateTimeStringToOffsetDateTime(makerDateTimeFrom, dateFormat, locale, LocalTime.MIN);
}

public OffsetDateTime getMakerDateTimeTo() {
return DateUtils.convertDateTimeStringToOffsetDateTime(makerDateTimeTo, dateFormat, locale, LocalTime.MAX);
OffsetDateTime parsed = tryParseDayMonthYear(makerDateTimeTo, LocalTime.MAX);
return parsed != null ? parsed
: DateUtils.convertDateTimeStringToOffsetDateTime(makerDateTimeTo, dateFormat, locale, LocalTime.MAX);
}

private static final DateTimeFormatter DAY_MONTH_YEAR = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.ENGLISH);

private static OffsetDateTime tryParseDayMonthYear(String value, LocalTime time) {
if (StringUtils.isBlank(value)) {
return null;
}
try {
LocalDate date = LocalDate.parse(value.trim(), DAY_MONTH_YEAR);
return date.atTime(time).atOffset(ZoneOffset.UTC);
} catch (DateTimeParseException e) {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,103 @@ public void testRejectDatatableCreationCleansUpOrphanedTable(String apptableName
}
}

@Test
public void testMakerCheckerUsernameFilter() {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(true));
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_SAME_MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(false));

try {
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("CREATE_CLIENT", true);
rolesHelper.updatePermissions(putPermissionsRequest);

Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
Map<String, Boolean> permissionMap = Map.of("CREATE_CLIENT", true, "CREATE_CLIENT_CHECKER", true);
RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap);
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);

String maker1 = Utils.uniqueRandomStringGenerator("user", 8);
String maker2 = Utils.uniqueRandomStringGenerator("user", 8);
UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker1, "A1b2c3d4e5f$", "resourceId");
UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker2, "A1b2c3d4e5f$", "resourceId");

RequestSpecification maker1RequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker1, "A1b2c3d4e5f$"));
RequestSpecification maker2RequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker2, "A1b2c3d4e5f$"));

ClientHelper.createClient(maker1RequestSpec, this.responseSpec);
ClientHelper.createClient(maker2RequestSpec, this.responseSpec);

List<Map<String, Object>> maker1Results = makercheckersHelper
.getMakerCheckerList(Map.of("username", maker1, "actionName", "CREATE", "entityName", "CLIENT"));
assertEquals(1, maker1Results.size(), "Username filter should return only maker1's commands");
assertEquals(maker1, maker1Results.get(0).get("maker"));

List<Map<String, Object>> maker2Results = makercheckersHelper
.getMakerCheckerList(Map.of("username", maker2, "actionName", "CREATE", "entityName", "CLIENT"));
assertEquals(1, maker2Results.size(), "Username filter should return only maker2's commands");
assertEquals(maker2, maker2Results.get(0).get("maker"));

List<Map<String, Object>> noResults = makercheckersHelper.getMakerCheckerList(Map.of("username", "nonexistentuserxyz_999"));
assertEquals(0, noResults.size(), "Unknown username should return no results");
} finally {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(false));
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_SAME_MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(true));
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("CREATE_CLIENT", false);
rolesHelper.updatePermissions(putPermissionsRequest);
}
}

@Test
public void testMakerCheckerDateFilterWithDayMonthYearFormat() {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(true));
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_SAME_MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(false));

try {
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("CREATE_CLIENT", true);
rolesHelper.updatePermissions(putPermissionsRequest);

Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
Map<String, Boolean> permissionMap = Map.of("CREATE_CLIENT", true, "CREATE_CLIENT_CHECKER", true);
RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap);
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);

String maker = Utils.uniqueRandomStringGenerator("user", 8);
final Integer makerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker,
"A1b2c3d4e5f$", "resourceId");
RequestSpecification makerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker, "A1b2c3d4e5f$"));

ClientHelper.createClient(makerRequestSpec, this.responseSpec);

// "dd MMMM yyyy" format without dateFormat/locale — previously caused 500 error
List<Map<String, Object>> fromOnly = makercheckersHelper.getMakerCheckerList(
Map.of("makerId", makerUserId.toString(), "makerDateTimeFrom", "01 January 2020"));
assertEquals(1, fromOnly.size(), "'dd MMMM yyyy' from-date filter should include today's pending command");

List<Map<String, Object>> fromAndTo = makercheckersHelper.getMakerCheckerList(Map.of("makerId", makerUserId.toString(),
"makerDateTimeFrom", "01 January 2020", "makerDateTimeTo", "31 December 2030"));
assertEquals(1, fromAndTo.size(), "'dd MMMM yyyy' date range filter should include today's pending command");

List<Map<String, Object>> pastRange = makercheckersHelper.getMakerCheckerList(Map.of("makerId", makerUserId.toString(),
"makerDateTimeFrom", "01 January 2020", "makerDateTimeTo", "31 December 2020"));
assertEquals(0, pastRange.size(), "Past date range should exclude today's pending command");
} finally {
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(false));
globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_SAME_MAKER_CHECKER,
new PutGlobalConfigurationsRequest().enabled(true));
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("CREATE_CLIENT", false);
rolesHelper.updatePermissions(putPermissionsRequest);
}
}

private Integer createSavingsProductDailyPosting() {
final String savingsProductJSON = this.savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
.withInterestPostingPeriodTypeAsDaily().withInterestCalculationPeriodTypeAsDailyBalance().build();
Expand Down
Loading