FINERACT-2076: SQL query optimization

This commit is contained in:
Aleksandar Vidakovic
2024-04-25 14:08:04 +02:00
committed by Aleksandar Vidakovic
parent 039bca440b
commit a022a51189
85 changed files with 1186 additions and 1193 deletions
@@ -67,6 +67,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.springframework.stereotype.Component;
@@ -92,6 +93,7 @@ public class JournalEntriesApiResource {
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -147,8 +149,10 @@ public class JournalEntriesApiResource {
submittedOnDateTo = submittedOnDateToParam.getDate("submittedOnDateTo", dateFormat, locale);
}
final SearchParameters searchParameters = SearchParameters.forJournalEntries(officeId, offset, limit, orderBy, sortOrder, loanId,
savingsId);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).officeId(officeId).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).loanId(loanId).savingsId(savingsId).build();
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(transactionDetails,
runningBalance);
@@ -246,7 +250,7 @@ public class JournalEntriesApiResource {
@QueryParam("entryId") final Long entryId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser();
String transactionId = "P" + entryId;
SearchParameters params = SearchParameters.forPagination(offset, limit);
SearchParameters params = SearchParameters.builder().limit(limit).offset(offset).build();
Page<JournalEntryData> entries = this.journalEntryReadPlatformService.retrieveAll(params, null, null, null, null, null, null,
transactionId, PortfolioProductType.PROVISIONING.getValue(), null);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -264,7 +264,7 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
whereClose = " and ";
}
if (searchParameters.isOfficeIdPassed()) {
if (searchParameters.hasOfficeId()) {
sqlBuilder.append(whereClose).append(" journalEntry.office_id = ?");
objectArray[arrayPos] = searchParameters.getOfficeId();
arrayPos = arrayPos + 1;
@@ -272,7 +272,7 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
whereClose = " and ";
}
if (searchParameters.isCurrencyCodePassed()) {
if (searchParameters.hasCurrencyCode()) {
sqlBuilder.append(whereClose).append(" journalEntry.currency_code = ?");
objectArray[arrayPos] = searchParameters.getCurrencyCode();
arrayPos = arrayPos + 1;
@@ -339,7 +339,7 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
}
}
if (searchParameters.isLoanIdPassed()) {
if (searchParameters.hasLoanId()) {
sqlBuilder.append(whereClose)
.append(" journalEntry.loan_transaction_id in (select id from m_loan_transaction where loan_id = ?)");
objectArray[arrayPos] = searchParameters.getLoanId();
@@ -347,18 +347,18 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
whereClose = " and ";
}
if (searchParameters.isSavingsIdPassed()) {
if (searchParameters.hasSavingsId()) {
sqlBuilder.append(whereClose).append(
" journalEntry.savings_transaction_id in (select id from m_savings_account_transaction where savings_account_id = ?)");
objectArray[arrayPos] = searchParameters.getSavingsId();
arrayPos = arrayPos + 1;
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
}
@@ -366,9 +366,9 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
sqlBuilder.append(" order by journalEntry.entry_date, journalEntry.id");
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -502,10 +502,6 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
private Page<JournalEntryData> retrieveContraTransactions(final Long officeId, final Long contraId, final String transactionId,
final String currencyCode) {
final Integer offset = 0;
final Integer limit = null;
final String orderBy = "journalEntry.id";
final String sortOrder = "ASC";
final Integer entityType = null;
final Boolean onlyManualEntries = null;
final LocalDate fromDate = null;
@@ -513,11 +509,10 @@ public class JournalEntryReadPlatformServiceImpl implements JournalEntryReadPlat
final LocalDate submittedOnDateFrom = null;
final LocalDate submittedOnDateTo = null;
final JournalEntryAssociationParametersData associationParametersData = null;
final Long loanId = null;
final Long savingsId = null;
final SearchParameters searchParameters = SearchParameters.forJournalEntries(officeId, offset, limit, orderBy, sortOrder, loanId,
savingsId, currencyCode);
final SearchParameters searchParameters = SearchParameters.builder().orphansOnly(false).officeId(officeId).offset(0)
.orderBy("journalEntry.id").sortOrder("ASC").currencyCode(currencyCode).build();
return retrieveAll(searchParameters, contraId, onlyManualEntries, fromDate, toDate, submittedOnDateFrom, submittedOnDateTo,
transactionId, entityType, associationParametersData);
@@ -31,7 +31,6 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.adhocquery.api.AdHocJsonInputParams;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
@Getter
@Setter
@@ -68,10 +67,7 @@ public class AdHoc extends AbstractAuditableCustom {
public static AdHoc fromJson(final JsonCommand command) {
final String name = command.stringValueOfParameterNamed(AdHocJsonInputParams.NAME.getValue());
String commandQuery = command.stringValueOfParameterNamed(AdHocJsonInputParams.QUERY.getValue());
SQLInjectionValidator.validateAdhocQuery(commandQuery);
final String query = commandQuery;
final String query = command.stringValueOfParameterNamed(AdHocJsonInputParams.QUERY.getValue());
final String tableName = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLENAME.getValue());
final String tableFields = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLEFIELDS.getValue());
final String email = command.stringValueOfParameterNamed(AdHocJsonInputParams.EMAIL.getValue());
@@ -21,6 +21,7 @@ package org.apache.fineract.adhocquery.service;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.adhocquery.api.AdHocJsonInputParams;
import org.apache.fineract.adhocquery.domain.AdHoc;
import org.apache.fineract.adhocquery.domain.AdHocRepository;
import org.apache.fineract.adhocquery.exception.AdHocNotFoundException;
@@ -30,6 +31,7 @@ import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuild
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.NonTransientDataAccessException;
import org.springframework.orm.jpa.JpaSystemException;
@@ -42,6 +44,7 @@ public class AdHocWritePlatformServiceJpaRepositoryImpl implements AdHocWritePla
private final PlatformSecurityContext context;
private final AdHocRepository adHocRepository;
private final AdHocDataValidator adHocCommandFromApiJsonDeserializer;
private final SqlValidator sqlValidator;
@Transactional
@Override
@@ -52,6 +55,10 @@ public class AdHocWritePlatformServiceJpaRepositoryImpl implements AdHocWritePla
this.adHocCommandFromApiJsonDeserializer.validateForCreate(command.json());
String commandQuery = command.stringValueOfParameterNamed(AdHocJsonInputParams.QUERY.getValue());
sqlValidator.validate("adhoc", commandQuery);
final AdHoc entity = AdHoc.fromJson(command);
this.adHocRepository.saveAndFlush(entity);
@@ -26,6 +26,7 @@ import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
import org.apache.fineract.adhocquery.service.AdHocWritePlatformServiceJpaRepositoryImpl;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -51,8 +52,8 @@ public class AdhocQueryConfiguration {
@Bean
@ConditionalOnMissingBean(AdHocWritePlatformService.class)
public AdHocWritePlatformService adHocWritePlatformService(PlatformSecurityContext context, AdHocRepository adHocRepository,
AdHocDataValidator adHocCommandFromApiJsonDeserializer) {
return new AdHocWritePlatformServiceJpaRepositoryImpl(context, adHocRepository, adHocCommandFromApiJsonDeserializer) {
AdHocDataValidator adHocCommandFromApiJsonDeserializer, SqlValidator sqlValidator) {
return new AdHocWritePlatformServiceJpaRepositoryImpl(context, adHocRepository, adHocCommandFromApiJsonDeserializer, sqlValidator) {
};
}
@@ -49,6 +49,7 @@ import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSeria
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.SQLBuilder;
import org.springframework.stereotype.Component;
@@ -73,6 +74,7 @@ public class AuditsApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final DefaultToApiJsonSerializer<AuditData> toApiJsonSerializer;
private final DefaultToApiJsonSerializer<AuditSearchData> toApiJsonSerializerSearchTemplate;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -106,7 +108,10 @@ public class AuditsApiResource {
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final PaginationParameters parameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final PaginationParameters parameters = PaginationParameters.builder().paged(Boolean.TRUE.equals(paged)).limit(limit).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final SQLBuilder extraCriteria = getExtraCriteria(actionName, entityName, resourceId, makerId, makerDateTimeFrom, makerDateTimeTo,
checkerId, checkerDateTimeFrom, checkerDateTimeTo, processingResult, officeId, groupId, clientId, loanId, savingsAccountId);
@@ -168,7 +168,7 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
@Override
public Collection<AuditData> retrieveAuditEntries(final SQLBuilder extraCriteria, final boolean includeJson) {
return retrieveEntries("audit", extraCriteria, " order by aud.id DESC limit " + PaginationParameters.getCheckedLimit(null),
return retrieveEntries("audit", extraCriteria, " order by aud.id DESC limit " + PaginationParameters.DEFAULT_MAX_LIMIT,
includeJson);
}
@@ -185,14 +185,14 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
sqlBuilder.append(rm.schema(includeJson, hierarchy));
sqlBuilder.append(' ').append(extraCriteria.getSQLTemplate());
if (parameters.isOrderByRequested()) {
if (parameters.hasOrderBy()) {
sqlBuilder.append(' ').append(parameters.orderBySql());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), parameters.orderBySql());
} else {
sqlBuilder.append(' ').append(' ').append(" order by aud.id DESC");
}
if (parameters.isLimited()) {
if (parameters.hasLimit()) {
sqlBuilder.append(' ').append(parameters.limitSql());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), parameters.limitSql());
}
@@ -272,7 +272,7 @@ public class BulkImportWorkbookPopulatorServiceImpl implements BulkImportWorkboo
if (officeId == null) {
Boolean includeAllOffices = Boolean.TRUE;
offices = (List) this.officeReadPlatformService.retrieveAllOffices(includeAllOffices,
new SearchParameters(null, null, null, null, null, null, null, null, "id", "asc", null, null, null, null, null, null));
SearchParameters.builder().orderBy("id").sortOrder("asc").build());
} else {
offices = new ArrayList<>();
offices.add(this.officeReadPlatformService.retrieveOffice(officeId));
@@ -341,7 +341,7 @@ public class BulkImportWorkbookPopulatorServiceImpl implements BulkImportWorkboo
if (officeId == null) {
centers = (List<CenterData>) this.centerReadPlatformService.retrieveAll(null, null);
} else {
SearchParameters searchParameters = SearchParameters.from(officeId, null, null, null);
SearchParameters searchParameters = SearchParameters.builder().officeId(officeId).build();
centers = (List<CenterData>) centerReadPlatformService.retrieveAll(searchParameters, null);
}
@@ -359,7 +359,7 @@ public class BulkImportWorkbookPopulatorServiceImpl implements BulkImportWorkboo
}
}
} else {
SearchParameters searchParameters = SearchParameters.from(officeId, null, null, null);
SearchParameters searchParameters = SearchParameters.builder().officeId(officeId).build();
Page<ClientData> clientDataPage = this.clientReadPlatformService.retrieveAll(searchParameters);
if (clientDataPage != null) {
clients = new ArrayList<>();
@@ -420,7 +420,7 @@ public class BulkImportWorkbookPopulatorServiceImpl implements BulkImportWorkboo
if (officeId == null) {
groups = (List<GroupGeneralData>) this.groupReadPlatformService.retrieveAll(null, null);
} else {
SearchParameters searchParameters = SearchParameters.from(officeId, null, null, null);
SearchParameters searchParameters = SearchParameters.builder().officeId(officeId).build();
groups = (List<GroupGeneralData>) groupReadPlatformService.retrieveAll(searchParameters, null);
}
@@ -448,7 +448,7 @@ public class BulkImportWorkbookPopulatorServiceImpl implements BulkImportWorkboo
if (officeId == null) {
loanAccounts = loanReadPlatformService.retrieveAll(null).getPageItems();
} else {
SearchParameters searchParameters = SearchParameters.from(officeId, null, null, null);
SearchParameters searchParameters = SearchParameters.builder().officeId(officeId).build();
loanAccounts = loanReadPlatformService.retrieveAll(searchParameters).getPageItems();
}
return loanAccounts;
@@ -48,6 +48,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Component;
@Path("/v1/email")
@@ -63,6 +64,7 @@ public class EmailApiResource {
private final DefaultToApiJsonSerializer<EmailData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final SqlValidator sqlValidator;
@GET
public String retrieveAllEmails(@Context final UriInfo uriInfo) {
@@ -78,7 +80,10 @@ public class EmailApiResource {
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forEmailCampaign(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
Collection<EmailData> emailMessages = readPlatformService.retrieveAllPending(searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, emailMessages);
@@ -91,7 +96,10 @@ public class EmailApiResource {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forEmailCampaign(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
Collection<EmailData> emailMessages = readPlatformService.retrieveAllSent(searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -131,7 +139,10 @@ public class EmailApiResource {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forEmailCampaign(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
Collection<EmailData> emailMessages = readPlatformService.retrieveAllFailed(searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -58,6 +58,7 @@ import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Component;
@Path("/v1/smscampaigns")
@@ -74,6 +75,7 @@ public class SmsCampaignApiResource {
private final DefaultToApiJsonSerializer<CampaignPreviewData> previewCampaignMessageDefaultToApiJsonSerializer;
private final SmsCampaignWritePlatformService smsCampaignWritePlatformService;
private final PlatformSecurityContext context;
private final SqlValidator sqlValidator;
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "SMS_CAMPAIGN";
@@ -142,7 +144,10 @@ public class SmsCampaignApiResource {
public String retrieveAllEmails(@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder, @Context final UriInfo uriInfo) {
platformSecurityContext.authenticatedUser().validateHasReadPermission(SmsCampaignConstants.RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forSMSCampaign(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
Page<SmsCampaignData> smsCampaignDataCollection = smsCampaignReadPlatformService.retrieveAll(searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, smsCampaignDataCollection);
@@ -94,9 +94,9 @@ public class SmsCampaignReadPlatformServiceImpl implements SmsCampaignReadPlatfo
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
sqlBuilder.append(this.smsCampaignMapper.schema() + " where sc.is_visible = ? ");
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -77,7 +77,7 @@ public class EntityDatatableChecksApiResource {
@QueryParam("productId") @Parameter(description = "productId") final Long productId,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
@QueryParam("limit") @Parameter(description = "limit") final Integer limit) {
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).build();
final Page<EntityDataTableChecksData> result = this.readEntityDatatableChecksService.retrieveAll(searchParameters, status, entity,
productId);
@@ -24,7 +24,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
@@ -34,17 +33,23 @@ import org.apache.fineract.infrastructure.dataqueries.data.ReportExportType;
import org.apache.fineract.infrastructure.dataqueries.service.export.DatatableReportExportService;
import org.apache.fineract.infrastructure.dataqueries.service.export.ResponseHolder;
import org.apache.fineract.infrastructure.report.annotation.ReportService;
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
import org.apache.fineract.infrastructure.report.service.AbstractReportingProcessService;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Service;
@Service
@ReportService(type = { "Table", "Chart", "SMS" })
@RequiredArgsConstructor
@Slf4j
public class DatatableReportingProcessService implements ReportingProcessService {
public class DatatableReportingProcessService extends AbstractReportingProcessService {
private final List<DatatableReportExportService> exportServices;
public DatatableReportingProcessService(List<DatatableReportExportService> exportServices, SqlValidator sqlValidator) {
super(sqlValidator);
this.exportServices = exportServices;
}
@Override
public Response processRequest(String reportName, MultivaluedMap<String, String> queryParams) {
boolean isSelfServiceUserReport = Boolean.parseBoolean(
@@ -109,9 +109,9 @@ public class EntityDatatableChecksReadPlatformServiceImpl implements EntityDatat
paramList.add(productId);
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -108,8 +108,8 @@ import org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoun
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableSystemErrorException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlInjectionPreventerService;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
import org.apache.fineract.portfolio.search.data.AdvancedQueryData;
import org.apache.fineract.portfolio.search.data.ColumnFilterData;
import org.apache.fineract.portfolio.search.service.SearchUtil;
@@ -148,6 +148,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private final SqlInjectionPreventerService preventSqlInjectionService;
private final DatatableKeywordGenerator datatableKeywordGenerator;
private final SqlValidator sqlValidator;
private final SearchUtil searchUtil;
@Override
public List<DatatableData> retrieveDatatableNames(final String appTable) {
@@ -185,7 +187,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Override
public DatatableData retrieveDatatable(final String datatable) {
// PERMITTED datatables
SQLInjectionValidator.validateSQLInput(datatable);
sqlValidator.validate(datatable);
final String sql = "select application_table_name, registered_table_name, entity_subtype from x_registered_table "
+ " where exists (select 'f' from m_appuser_role ur join m_role r on r.id = ur.role_id"
+ " left join m_role_permission rp on rp.role_id = r.id left join m_permission p on p.id = rp.permission_id"
@@ -213,21 +215,21 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
public List<JsonObject> queryDataTable(@NotNull String datatable, @NotNull String columnName, String columnValueString,
@NotNull String resultColumnsString) {
datatable = validateDatatableRegistered(datatable);
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil
.mapHeadersToName(genericDataService.fillResultsetColumnHeaders(datatable));
List<String> resultColumns = asList(resultColumnsString.split(","));
List<String> selectColumns = SearchUtil.validateToJdbcColumnNames(resultColumns, headersByName, false);
ResultsetColumnHeaderData column = SearchUtil.validateToJdbcColumn(columnName, headersByName, false);
List<String> selectColumns = searchUtil.validateToJdbcColumnNames(resultColumns, headersByName, false);
ResultsetColumnHeaderData column = searchUtil.validateToJdbcColumn(columnName, headersByName, false);
Object columnValue = SearchUtil.parseJdbcColumnValue(column, columnValueString, null, null, null, false, sqlGenerator);
Object columnValue = searchUtil.parseJdbcColumnValue(column, columnValueString, null, null, null, false, sqlGenerator);
String sql = sqlGenerator.buildSelect(selectColumns, null, false) + " " + sqlGenerator.buildFrom(datatable, null, false) + " WHERE "
+ EQ.formatPlaceholder(sqlGenerator, column.getColumnName(), 1, null);
SqlRowSet rowSet = jdbcTemplate.queryForRowSet(sql, columnValue); // NOSONAR
List<JsonObject> results = new ArrayList<>();
while (rowSet.next()) {
SearchUtil.extractJsonResult(rowSet, selectColumns, resultColumns, results);
searchUtil.extractJsonResult(rowSet, selectColumns, resultColumns, results);
}
return results;
}
@@ -240,12 +242,12 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
AdvancedQueryData request = pagedRequest.getRequest().orElseThrow();
dataTableValidator.validateTableSearch(request);
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil
.mapHeadersToName(genericDataService.fillResultsetColumnHeaders(datatable));
String pkColumn = SearchUtil.getFiltered(headersByName.values(), ResultsetColumnHeaderData::getIsColumnPrimaryKey).getColumnName();
String pkColumn = searchUtil.getFiltered(headersByName.values(), ResultsetColumnHeaderData::getIsColumnPrimaryKey).getColumnName();
List<ColumnFilterData> columnFilters = request.getNonNullFilters();
columnFilters.forEach(e -> e.setColumn(SearchUtil.validateToJdbcColumnName(e.getColumn(), headersByName, false)));
columnFilters.forEach(e -> e.setColumn(searchUtil.validateToJdbcColumnName(e.getColumn(), headersByName, false)));
List<String> resultColumns = request.getNonNullResultColumns();
List<String> selectColumns;
@@ -254,14 +256,14 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
selectColumns = new ArrayList<>();
selectColumns.add(pkColumn);
} else {
selectColumns = SearchUtil.validateToJdbcColumnNames(resultColumns, headersByName, false);
selectColumns = searchUtil.validateToJdbcColumnNames(resultColumns, headersByName, false);
}
PageRequest pageable = pagedRequest.toPageable();
PageRequest sortPageable;
if (pageable.getSort().isSorted()) {
List<Sort.Order> orders = pageable.getSort().toList();
sortPageable = pageable.withSort(Sort.by(orders.stream()
.map(e -> e.withProperty(SearchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList()));
.map(e -> e.withProperty(searchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList()));
} else {
pageable = pageable.withSort(Sort.Direction.DESC, pkColumn);
sortPageable = pageable;
@@ -275,7 +277,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
String from = " " + sqlGenerator.buildFrom(datatable, null, false);
StringBuilder where = new StringBuilder();
ArrayList<Object> params = new ArrayList<>();
SearchUtil.buildQueryCondition(columnFilters, where, params, null, headersByName, dateFormat, dateTimeFormat, locale, false,
searchUtil.buildQueryCondition(columnFilters, where, params, null, headersByName, dateFormat, dateTimeFormat, locale, false,
sqlGenerator);
List<JsonObject> results = new ArrayList<>();
@@ -297,7 +299,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
SqlRowSet rowSet = jdbcTemplate.queryForRowSet(query.toString(), args);
while (rowSet.next()) {
SearchUtil.extractJsonResult(rowSet, selectColumns, resultColumns, results);
searchUtil.extractJsonResult(rowSet, selectColumns, resultColumns, results);
}
return PageableExecutionUtils.getPage(results, pageable, () -> totalElements);
}
@@ -315,19 +317,19 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
datatable = validateDatatableRegistered(datatable);
context.authenticatedUser().validateHasDatatableReadPermission(datatable);
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil
.mapHeadersToName(genericDataService.fillResultsetColumnHeaders(datatable));
List<String> thisSelectColumns = SearchUtil.validateToJdbcColumnNames(resultColumns, headersByName, true);
List<String> thisSelectColumns = searchUtil.validateToJdbcColumnNames(resultColumns, headersByName, true);
if (columnFilters != null) {
columnFilters.forEach(e -> e.setColumn(SearchUtil.validateToJdbcColumnName(e.getColumn(), headersByName, false)));
columnFilters.forEach(e -> e.setColumn(searchUtil.validateToJdbcColumnName(e.getColumn(), headersByName, false)));
}
select.append(sqlGenerator.buildSelect(thisSelectColumns, alias, true));
selectColumns.addAll(thisSelectColumns);
String joinType = "LEFT";
if (SearchUtil.buildQueryCondition(columnFilters, where, params, alias, headersByName, dateFormat, dateTimeFormat, locale, true,
if (searchUtil.buildQueryCondition(columnFilters, where, params, alias, headersByName, dateFormat, dateTimeFormat, locale, true,
sqlGenerator)) {
joinType = null; // INNER
}
@@ -674,7 +676,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
validateDatatableName(datatableName);
int rowCount = getDatatableRowCount(datatableName);
final List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService.fillResultsetColumnHeaders(datatableName);
final Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition = SearchUtil.mapHeadersToName(columnHeaderData);
final Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition = searchUtil.mapHeadersToName(columnHeaderData);
final boolean isConstraintApproach = this.configurationDomainService.isConstraintApproachEnabledForDatatables();
@@ -1283,7 +1285,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(entityTable, appTableId);
List<ResultsetColumnHeaderData> columnHeaders = genericDataService.fillResultsetColumnHeaders(dataTableName);
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil.mapHeadersToName(columnHeaders);
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil.mapHeadersToName(columnHeaders);
final Type typeOfMap = new TypeToken<Map<String, String>>() {}.getType();
final Map<String, String> dataParams = fromJsonHelper.extractDataMap(typeOfMap, json);
@@ -1302,12 +1304,12 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
if (isTechnicalParam(entry.getKey())) {
continue;
}
ResultsetColumnHeaderData columnHeader = SearchUtil.validateToJdbcColumn(entry.getKey(), headersByName, false);
ResultsetColumnHeaderData columnHeader = searchUtil.validateToJdbcColumn(entry.getKey(), headersByName, false);
if (!isUserInsertable(entityTable, columnHeader)) {
continue;
}
insertColumns.add(columnHeader.getColumnName());
params.add(SearchUtil.parseJdbcColumnValue(columnHeader, entry.getValue(), dateFormat, dateTimeFormat, locale, false,
params.add(searchUtil.parseJdbcColumnValue(columnHeader, entry.getValue(), dateFormat, dateTimeFormat, locale, false,
sqlGenerator));
}
if (addScore) {
@@ -1318,7 +1320,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
} else {
StringBuilder scoreSql = new StringBuilder("SELECT SUM(code_score) FROM m_code_value WHERE m_code_value.");
ArrayList<Object> scoreParams = new ArrayList<>();
SearchUtil.buildCondition("id", BIGINT, IN, scoreIds, scoreSql, scoreParams, null, sqlGenerator);
searchUtil.buildCondition("id", BIGINT, IN, scoreIds, scoreSql, scoreParams, null, sqlGenerator);
Integer score = jdbcTemplate.queryForObject(scoreSql.toString(), Integer.class, scoreParams.toArray(Object[]::new));
scoreValue = score == null ? 0 : score;
}
@@ -1404,7 +1406,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
throw new PlatformDataIntegrityException("error.msg.attempting.multiple.update",
"Application table: " + dataTableName + " Foreign key id: " + appTableId);
}
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil.mapHeadersToName(columnHeaders);
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil.mapHeadersToName(columnHeaders);
final List<Object> existingValues = existingRows.getData().get(0).getRow();
HashMap<ResultsetColumnHeaderData, Object> valuesByHeader = columnHeaders.stream().collect(HashMap::new,
(map, e) -> map.put(e, existingValues.get(map.size())), (map, map2) -> {});
@@ -1426,13 +1428,13 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
if (isTechnicalParam(entry.getKey())) {
continue;
}
ResultsetColumnHeaderData columnHeader = SearchUtil.validateToJdbcColumn(entry.getKey(), headersByName, false);
ResultsetColumnHeaderData columnHeader = searchUtil.validateToJdbcColumn(entry.getKey(), headersByName, false);
if (!isUserUpdatable(entityTable, columnHeader)) {
continue;
}
String columnName = columnHeader.getColumnName();
Object existingValue = valuesByHeader.get(columnHeader);
Object columnValue = SearchUtil.parseColumnValue(columnHeader, entry.getValue(), dateFormat, dateTimeFormat, locale, false,
Object columnValue = searchUtil.parseColumnValue(columnHeader, entry.getValue(), dateFormat, dateTimeFormat, locale, false,
sqlGenerator);
if ((columnHeader.getColumnType().isDecimalType() && MathUtil.isEqualTo((BigDecimal) existingValue, (BigDecimal) columnValue))
|| (existingValue == null ? columnValue == null : existingValue.equals(columnValue))) {
@@ -1445,7 +1447,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
}
Long primaryKey = datatableId == null ? appTableId : datatableId;
if (!updateColumns.isEmpty()) {
ResultsetColumnHeaderData pkColumn = SearchUtil.getFiltered(columnHeaders, ResultsetColumnHeaderData::getIsColumnPrimaryKey);
ResultsetColumnHeaderData pkColumn = searchUtil.getFiltered(columnHeaders, ResultsetColumnHeaderData::getIsColumnPrimaryKey);
params.add(primaryKey);
final String sql = sqlGenerator.buildUpdate(dataTableName, updateColumns, headersByName) + " WHERE " + pkColumn.getColumnName()
+ " = ?";
@@ -1533,7 +1535,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
final boolean multiRow = isMultirowDatatable(columnHeaders);
String whereClause = getFKField(entityTable) + " = " + appTableId;
SQLInjectionValidator.validateSQLInput(whereClause);
sqlValidator.validate(whereClause);
String sql = "select * from " + sqlGenerator.escape(dataTableName) + " where " + whereClause;
// id only used for reading a specific entry that belongs to appTableId (in a one to many datatable)
@@ -1636,7 +1638,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@NotNull
private EntityTables queryForApplicationEntity(final String datatable) {
SQLInjectionValidator.validateSQLInput(datatable);
sqlValidator.validate(datatable);
final String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = ?";
final SqlRowSet rowSet = jdbcTemplate.queryForRowSet(sql, datatable); // NOSONAR
@@ -1681,7 +1683,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
} else if (!name.matches(DATATABLE_NAME_REGEX_PATTERN)) {
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.invalid.name.regex", "Invalid data table name.", name);
}
SQLInjectionValidator.validateSQLInput(name);
sqlValidator.validate(name);
}
private String validateDatatableRegistered(String datatable) {
@@ -1750,7 +1752,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
}
private boolean isMultirowDatatable(final List<ResultsetColumnHeaderData> columnHeaders) {
return SearchUtil.findFiltered(columnHeaders, e -> e.isNamed(TABLE_FIELD_ID)) != null;
return searchUtil.findFiltered(columnHeaders, e -> e.isNamed(TABLE_FIELD_ID)) != null;
}
private String datatableColumnNameToCodeValueName(final String columnName, final String code) {
@@ -31,7 +31,9 @@ import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDa
import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlInjectionPreventerService;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.portfolio.search.service.SearchUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -50,9 +52,10 @@ public class DataQueriesAutoConfiguration {
final ConfigurationDomainService configurationDomainService, final CodeReadPlatformService codeReadPlatformService,
final DataTableValidator dataTableValidator, final ColumnValidator columnValidator,
final NamedParameterJdbcTemplate namedParameterJdbcTemplate, final SqlInjectionPreventerService preventSqlInjectionService,
DatatableKeywordGenerator datatableKeywordGenerator) {
DatatableKeywordGenerator datatableKeywordGenerator, SqlValidator sqlValidator, SearchUtil searchUtil) {
return new ReadWriteNonCoreDataServiceImpl(jdbcTemplate, databaseTypeResolver, sqlGenerator, context, fromJsonHelper,
genericDataService, fromApiJsonDeserializer, configurationDomainService, codeReadPlatformService, dataTableValidator,
columnValidator, namedParameterJdbcTemplate, preventSqlInjectionService, datatableKeywordGenerator);
columnValidator, namedParameterJdbcTemplate, preventSqlInjectionService, datatableKeywordGenerator, sqlValidator,
searchUtil);
}
}
@@ -61,6 +61,7 @@ import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
import org.apache.fineract.infrastructure.jobs.service.SchedulerJobRunnerReadService;
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Component;
@Path("/v1/jobs")
@@ -79,6 +80,7 @@ public class SchedulerJobApiResource {
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
private final FineractProperties fineractProperties;
private final SqlValidator sqlValidator;
@GET
@Operation(summary = "Retrieve Scheduler Jobs", description = "Returns the list of jobs.\n" + "\n" + "Example Requests:\n" + "\n"
@@ -117,7 +119,10 @@ public class SchedulerJobApiResource {
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
final Page<JobDetailHistoryData> jobhistoryDetailData = this.schedulerJobRunnerReadService.retrieveJobHistory(jobId,
searchParameters);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -100,18 +100,18 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
sqlBuilder.append(jobHistoryMapper.schema());
sqlBuilder.append(" where job.id=?");
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -0,0 +1,48 @@
/**
* 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.report.service;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
public abstract class AbstractReportingProcessService implements ReportingProcessService {
private final SqlValidator sqlValidator;
protected AbstractReportingProcessService(SqlValidator sqlValidator) {
this.sqlValidator = sqlValidator;
}
@Override
public Map<String, String> getReportParams(final MultivaluedMap<String, String> queryParams) {
final Map<String, String> reportParams = new HashMap<>();
for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
if (entry.getKey().startsWith("R_")) {
String pKey = "${" + entry.getKey().substring(2) + "}";
String pValue = entry.getValue().get(0);
sqlValidator.validate(pValue);
reportParams.put(pKey, pValue);
}
}
return reportParams;
}
}
@@ -20,11 +20,9 @@ package org.apache.fineract.infrastructure.report.service;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.fineract.infrastructure.dataqueries.data.ReportExportType;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
public interface ReportingProcessService {
@@ -32,16 +30,5 @@ public interface ReportingProcessService {
List<ReportExportType> getAvailableExportTargets();
default Map<String, String> getReportParams(final MultivaluedMap<String, String> queryParams) {
final Map<String, String> reportParams = new HashMap<>();
for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
if (entry.getKey().startsWith("R_")) {
String pKey = "${" + entry.getKey().substring(2) + "}";
String pValue = entry.getValue().get(0);
SQLInjectionValidator.validateSQLInput(pValue);
reportParams.put(pKey, pValue);
}
}
return reportParams;
}
Map<String, String> getReportParams(MultivaluedMap<String, String> queryParams);
}
@@ -53,6 +53,7 @@ import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConst
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobData;
import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobReadPlatformService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Component;
@Path("/v1/" + ReportMailingJobConstants.REPORT_MAILING_JOB_RESOURCE_NAME)
@@ -66,6 +67,7 @@ public class ReportMailingJobApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final DefaultToApiJsonSerializer<ReportMailingJobData> reportMailingToApiJsonSerializer;
private final ReportMailingJobReadPlatformService reportMailingJobReadPlatformService;
private final SqlValidator sqlValidator;
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@@ -184,7 +186,10 @@ public class ReportMailingJobApiResource {
.validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
final SearchParameters searchParameters = SearchParameters.fromReportMailingJob(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
final Page<ReportMailingJobData> reportMailingJobData = this.reportMailingJobReadPlatformService
.retrieveAllReportMailingJobs(searchParameters);
@@ -43,6 +43,7 @@ import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConst
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobRunHistoryData;
import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobRunHistoryReadPlatformService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.springframework.stereotype.Component;
@Path("/v1/" + ReportMailingJobConstants.REPORT_MAILING_JOB_RUN_HISTORY_RESOURCE_NAME)
@@ -55,6 +56,7 @@ public class ReportMailingJobRunHistoryApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final DefaultToApiJsonSerializer<ReportMailingJobRunHistoryData> reportMailingToApiJsonSerializer;
private final ReportMailingJobRunHistoryReadPlatformService reportMailingJobRunHistoryReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -71,7 +73,10 @@ public class ReportMailingJobRunHistoryApiResource {
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
this.platformSecurityContext.authenticatedUser()
.validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
final SearchParameters searchParameters = SearchParameters.fromReportMailingJobRunHistory(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
final Page<ReportMailingJobRunHistoryData> reportMailingJobRunHistoryData = this.reportMailingJobRunHistoryReadPlatformService
.retrieveRunHistoryByJobId(reportMailingJobId, searchParameters);
@@ -71,10 +71,10 @@ public class ReportMailingJobReadPlatformServiceImpl implements ReportMailingJob
sqlStringBuilder.append(mapper.reportMailingJobSchema());
sqlStringBuilder.append(" where rmj.is_deleted = false");
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlStringBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlStringBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlStringBuilder.append(" ").append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlStringBuilder.toString(), searchParameters.getSortOrder());
}
@@ -82,9 +82,9 @@ public class ReportMailingJobReadPlatformServiceImpl implements ReportMailingJob
sqlStringBuilder.append(" order by rmj.name ");
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlStringBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlStringBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlStringBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -68,18 +68,18 @@ public class ReportMailingJobRunHistoryReadPlatformServiceImpl implements Report
queryParameters.add(reportMailingJobId);
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlStringBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlStringBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlStringBuilder.append(" ").append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlStringBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlStringBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlStringBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlStringBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -47,6 +47,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.sms.data.SmsData;
import org.apache.fineract.infrastructure.sms.service.SmsReadPlatformService;
import org.springframework.stereotype.Component;
@@ -66,6 +67,7 @@ public class SmsApiResource {
private final DefaultToApiJsonSerializer<SmsData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final SqlValidator sqlValidator;
@GET
public String retrieveAll(@Context final UriInfo uriInfo) {
@@ -99,7 +101,10 @@ public class SmsApiResource {
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forSMSCampaign(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
final DateFormat dateFormat = StringUtils.isBlank(rawDateFormat) ? null : new DateFormat(rawDateFormat);
@@ -225,10 +225,10 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
arrayPos = arrayPos + 1;
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
@@ -236,9 +236,9 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
sqlBuilder.append(" order by smo.submittedon_date, smo.id");
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -20,6 +20,8 @@ package org.apache.fineract.infrastructure.survey.service;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant;
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
@@ -27,33 +29,25 @@ import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeader
import org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.survey.data.ClientScoresOverview;
import org.apache.fineract.infrastructure.survey.data.LikelihoodStatus;
import org.apache.fineract.infrastructure.survey.data.SurveyDataTableData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service;
@Slf4j
@RequiredArgsConstructor
@Service
public class ReadSurveyServiceImpl implements ReadSurveyService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
private final SqlValidator sqlValidator;
private final GenericDataService genericDataService;
private final ReadWriteNonCoreDataService readWriteNonCoreDataService;
@Autowired
public ReadSurveyServiceImpl(final PlatformSecurityContext context, final JdbcTemplate jdbcTemplate,
final GenericDataService genericDataService, final ReadWriteNonCoreDataService readWriteNonCoreDataService) {
this.context = context;
this.jdbcTemplate = jdbcTemplate;
this.genericDataService = genericDataService;
this.readWriteNonCoreDataService = readWriteNonCoreDataService;
}
@Override
public List<SurveyDataTableData> retrieveAllSurveys() {
@@ -91,7 +85,7 @@ public class ReadSurveyServiceImpl implements ReadSurveyService {
@Override
public SurveyDataTableData retrieveSurvey(String surveyName) {
SQLInjectionValidator.validateSQLInput(surveyName);
sqlValidator.validate(surveyName);
final String sql = "select cf.enabled, application_table_name, registered_table_name, entity_subtype" + " from x_registered_table "
+ " left join c_configuration cf on x_registered_table.registered_table_name = cf.name " + " where exists" + " (select 'f'"
+ " from m_appuser_role ur " + " join m_role r on r.id = ur.role_id"
@@ -153,13 +147,13 @@ public class ReadSurveyServiceImpl implements ReadSurveyService {
+ " tz" + " JOIN ppi_likelihoods_ppi lkp on lkp.ppi_name = '" + surveyNames.getString("name") + "' AND enabled = '"
+ LikelihoodStatus.ENABLED + "' JOIN ppi_scores sc on score_from <= tz.score AND score_to >=tz.score"
+ " JOIN ppi_poverty_line pvl on pvl.likelihood_ppi_id = lkp.id AND pvl.score_id = sc.id"
+ " JOIN ppi_likelihoods lkh on lkh.id = lkp.likelihood_id " + " WHERE client_id = " + clientId);
+ " JOIN ppi_likelihoods lkh on lkh.id = lkp.likelihood_id " + " WHERE client_id = ?");
}
List<ClientScoresOverview> scoresOverviews = new ArrayList<>();
for (String sql : sqls) {
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql, clientId);
while (rs.next()) {
scoresOverviews.add(new ClientScoresOverview().setLikelihoodCode(rs.getString("code"))
@@ -41,6 +41,7 @@ import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.notification.data.NotificationData;
import org.apache.fineract.notification.service.NotificationReadPlatformService;
import org.springframework.stereotype.Component;
@@ -55,6 +56,7 @@ public class NotificationApiResource {
private final NotificationReadPlatformService notificationReadPlatformService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final ToApiJsonSerializer<NotificationData> toApiJsonSerializer;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -71,7 +73,10 @@ public class NotificationApiResource {
this.context.authenticatedUser();
final Page<NotificationData> notificationData;
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
if (!isRead) {
notificationData = this.notificationReadPlatformService.getAllUnreadNotifications(searchParameters);
} else {
@@ -135,18 +135,18 @@ public class NotificationReadPlatformServiceImpl implements NotificationReadPlat
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append(sql);
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -62,6 +62,7 @@ import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerialize
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
@@ -90,6 +91,7 @@ public class OfficesApiResource {
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final SqlValidator sqlValidator;
private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson();
@@ -105,7 +107,10 @@ public class OfficesApiResource {
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forOffices(orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().orphansOnly(false).isSelfUser(false).orderBy(orderBy)
.sortOrder(sortOrder).build();
final Collection<OfficeData> offices = readPlatformService.retrieveAllOffices(onlyManualEntries, searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, offices, RESPONSE_DATA_PARAMETERS);
@@ -159,12 +159,12 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
sqlBuilder.append(rm.officeSchema());
sqlBuilder.append(" where o.hierarchy like ? ");
if (searchParameters != null) {
if (searchParameters.isOrderByRequested()) {
sqlBuilder.append("order by ").append(searchParameters.getOrderBy());
if (searchParameters.hasOrderBy()) {
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
sqlBuilder.append("order by ").append(searchParameters.getOrderBy());
if (searchParameters.hasSortOrder()) {
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
}
} else {
sqlBuilder.append("order by o.hierarchy");
@@ -485,9 +485,9 @@ public class TellerManagementReadPlatformServiceImpl implements TellerManagement
+ " and renum.enum_value in ('PAY_CHARGE', 'WAIVE_CHARGE') "
+ " and (cli_txn.payment_detail_id IS NULL OR payType.is_cash_payment = true) ) " + " order by created_date ";
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sql += " ";
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sql += sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset());
} else {
sql += sqlGenerator.limit(searchParameters.getLimit());
@@ -47,6 +47,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.account.data.AccountTransferData;
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
import org.springframework.stereotype.Component;
@@ -62,6 +63,7 @@ public class AccountTransfersApiResource {
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -125,7 +127,11 @@ public class AccountTransfersApiResource {
this.context.authenticatedUser().validateHasReadPermission(AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(externalId, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final Page<AccountTransferData> transfers = this.accountTransfersReadPlatformService.retrieveAll(searchParameters, accountDetailId);
@@ -54,6 +54,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.account.data.AccountTransferData;
import org.apache.fineract.portfolio.account.data.StandingInstructionDTO;
import org.apache.fineract.portfolio.account.data.StandingInstructionData;
@@ -74,6 +75,7 @@ public class StandingInstructionApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -182,7 +184,11 @@ public class StandingInstructionApiResource {
this.context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(externalId, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final LocalDate startDateRange = null;
final LocalDate endDateRange = null;
@@ -212,8 +218,11 @@ public class StandingInstructionApiResource {
this.context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
StandingInstructionData standingInstructionData = this.standingInstructionReadPlatformService.retrieveOne(standingInstructionId);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(externalId, offset, limit, orderBy, sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
Page<AccountTransferData> transfers = null;
if (!associationParameters.isEmpty()) {
@@ -44,6 +44,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.account.data.StandingInstructionDTO;
import org.apache.fineract.portfolio.account.data.StandingInstructionHistoryData;
import org.apache.fineract.portfolio.account.service.StandingInstructionHistoryReadPlatformService;
@@ -59,6 +60,7 @@ public class StandingInstructionHistoryApiResource {
private final DefaultToApiJsonSerializer<StandingInstructionHistoryData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final StandingInstructionHistoryReadPlatformService standingInstructionHistoryReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -88,7 +90,11 @@ public class StandingInstructionHistoryApiResource {
final DateFormat dateFormat = StringUtils.isBlank(rawDateFormat) ? null : new DateFormat(rawDateFormat);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(externalId, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
LocalDate startDateRange = null;
LocalDate endDateRange = null;
if (fromDateParam != null) {
@@ -218,18 +218,18 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
finalObjectArray = new Object[] { accountDetailId };
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
@@ -287,18 +287,18 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
sqlBuilder.append(" where atsi.id = ?");
if (searchParameters != null) {
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -136,18 +136,18 @@ public class StandingInstructionHistoryReadPlatformServiceImpl implements Standi
}
final SearchParameters searchParameters = standingInstructionDTO.searchParameters();
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -305,18 +305,18 @@ public class StandingInstructionReadPlatformServiceImpl implements StandingInstr
}
final SearchParameters searchParameters = standingInstructionDTO.searchParameters();
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -102,7 +102,7 @@ public class ClientChargesApiResource {
ClientApiConstants.CLIENT_CHARGE_QUERY_PARAM_STATUS_VALUE_ACTIVE,
ClientApiConstants.CLIENT_CHARGE_QUERY_PARAM_STATUS_VALUE_INACTIVE });
}
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).build();
final Page<ClientChargeData> clientCharges = this.clientChargeReadPlatformService.retrieveClientCharges(clientId, chargeStatus,
pendingPayment, searchParameters);
@@ -311,7 +311,7 @@ public class ClientTransactionsApiResource {
private String getAllClientTransactions(Long clientId, UriInfo uriInfo, Integer offset, Integer limit) {
SearchParameters searchParameters = SearchParameters.forPagination(offset, limit);
SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).build();
final Page<ClientTransactionData> clientTransactions = clientTransactionReadPlatformService.retrieveAllTransactions(clientId,
searchParameters);
@@ -62,6 +62,7 @@ import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
import org.apache.fineract.portfolio.client.data.ClientData;
@@ -93,6 +94,7 @@ public class ClientsApiResource {
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final GuarantorReadPlatformService guarantorReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -443,8 +445,13 @@ public class ClientsApiResource {
final String firstname, final String lastname, final String status, final String hierarchy, final Integer offset,
final Integer limit, final String orderBy, final String sortOrder, final Boolean orphansOnly, final boolean isSelfUser) {
context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forClients(officeId, externalId, displayName, firstname, lastname,
status, hierarchy, offset, limit, orderBy, sortOrder, orphansOnly, isSelfUser);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
sqlValidator.validate(hierarchy);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).officeId(officeId).externalId(externalId)
.name(displayName).hierarchy(hierarchy).firstname(firstname).lastname(lastname).status(status).orphansOnly(orphansOnly)
.isSelfUser(isSelfUser).offset(offset).orderBy(orderBy).sortOrder(sortOrder).build();
final Page<ClientData> clientData = clientReadPlatformService.retrieveAll(searchParameters);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return toApiJsonSerializer.serialize(settings, clientData, ClientApiConstants.CLIENT_RESPONSE_DATA_PARAMETERS);
@@ -151,9 +151,9 @@ public class ClientChargeReadPlatformServiceImpl implements ClientChargeReadPlat
// apply limit and offsets
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -192,7 +192,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
sqlBuilder.append(" where (o.hierarchy like ? or transferToOffice.hierarchy like ?) ");
if (searchParameters != null) {
if (searchParameters.isSelfUser()) {
if (searchParameters.getIsSelfUser()) {
sqlBuilder.append(
" and c.id in (select umap.client_id from m_selfservice_user_client_mapping as umap where umap.appuser_id = ? ) ");
paramList.add(appUserID);
@@ -204,18 +204,18 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
sqlBuilder.append(" and (").append(extraCriteria).append(")");
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -267,12 +267,12 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
extraCriteria += " and c.lastname like ? ";
}
if (searchParameters.isScopedByOfficeHierarchy()) {
if (searchParameters.hasHierarchy()) {
paramList.add(searchParameters.getHierarchy() + "%");
extraCriteria += " and o.hierarchy like ? ";
}
if (searchParameters.isOrphansOnly()) {
if (searchParameters.getOrphansOnly()) {
extraCriteria += " and c.id NOT IN (select client_id from m_group_client) ";
}
@@ -143,9 +143,9 @@ public class ClientTransactionReadPlatformServiceImpl implements ClientTransacti
// apply limit and offsets
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -75,6 +75,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
import org.apache.fineract.portfolio.calendar.data.CalendarData;
@@ -113,6 +114,7 @@ public class CentersApiResource {
private final EntityDatatableChecksReadService entityDatatableChecksReadService;
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -177,10 +179,14 @@ public class CentersApiResource {
return this.toApiJsonSerializer.serialize(settings, staffCenterDataArray,
GroupingTypesApiConstants.STAFF_CENTER_RESPONSE_DATA_PARAMETERS);
}
final PaginationParameters parameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
final Boolean isOrphansOnly = false;
final SearchParameters searchParameters = SearchParameters.forGroups(officeId, staffId, externalId, name, hierarchy, offset, limit,
orderBy, sortOrder, isOrphansOnly);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
sqlValidator.validate(hierarchy);
final PaginationParameters parameters = PaginationParameters.builder().paged(Boolean.TRUE.equals(paged)).limit(limit).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).officeId(officeId).externalId(externalId)
.name(name).hierarchy(hierarchy).offset(offset).orderBy(orderBy).sortOrder(sortOrder).staffId(staffId).build();
if (parameters.isPaged()) {
final Page<CenterData> centers = this.centerReadPlatformService.retrievePagedAll(searchParameters, parameters);
return this.toApiJsonSerializer.serialize(settings, centers, GroupingTypesApiConstants.CENTER_RESPONSE_DATA_PARAMETERS);
@@ -74,6 +74,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData;
import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService;
import org.apache.fineract.portfolio.calendar.data.CalendarData;
@@ -130,6 +131,7 @@ public class GroupsApiResource {
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService;
private final GSIMReadPlatformService gsimReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -197,11 +199,17 @@ public class GroupsApiResource {
@QueryParam("orphansOnly") @Parameter(description = "orphansOnly") final Boolean orphansOnly) {
context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
final PaginationParameters parameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
sqlValidator.validate(hierarchy);
final PaginationParameters parameters = PaginationParameters.builder().paged(Boolean.TRUE.equals(paged)).limit(limit).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
final SearchParameters searchParameters = SearchParameters.forGroups(officeId, staffId, externalId, name, hierarchy, offset, limit,
orderBy, sortOrder, orphansOnly);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).isSelfUser(false).officeId(officeId)
.externalId(externalId).name(name).hierarchy(hierarchy).offset(offset).orderBy(orderBy).sortOrder(sortOrder)
.staffId(staffId).orphansOnly(orphansOnly).build();
if (parameters.isPaged()) {
final Page<GroupGeneralData> groups = groupReadPlatformService.retrievePagedAll(searchParameters, parameters);
return toApiJsonSerializer.serialize(settings, groups, GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
@@ -317,16 +317,16 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
final SQLBuilder extraCriteria = getCenterExtraCriteria(this.centerMapper.schema(), searchParameters);
extraCriteria.addNonNullCriteria("o.hierarchy like ", hierarchySearchString);
sqlBuilder.append(' ').append(extraCriteria.getSQLTemplate());
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy()).append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy(),
searchParameters.getSortOrder());
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -352,15 +352,15 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
extraCriteria.addNonNullCriteria("o.hierarchy like ", hierarchySearchString);
sqlBuilder.append(' ').append(extraCriteria.getSQLTemplate());
if (searchParameters != null) {
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy()).append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy(),
searchParameters.getSortOrder());
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -137,15 +137,15 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
final SQLBuilder extraCriteria = getGroupExtraCriteria(searchParameters);
extraCriteria.addCriteria(" o.hierarchy like ", hierarchySearchString);
sqlBuilder.append(" ").append(extraCriteria.getSQLTemplate());
if (parameters.isOrderByRequested()) {
if (parameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy()).append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy(),
searchParameters.getSortOrder());
}
if (parameters.isLimited()) {
if (parameters.hasLimit()) {
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
@@ -168,17 +168,17 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
sqlBuilder.append(" ").append(extraCriteria.getSQLTemplate());
if (searchParameters != null && searchParameters.isOrphansOnly()) {
if (searchParameters != null && searchParameters.getOrphansOnly()) {
sqlBuilder.append(" and g.parent_id is NULL");
}
if (parameters != null) {
if (parameters.isOrderByRequested()) {
if (parameters.hasOrderBy()) {
sqlBuilder.append(parameters.orderBySql());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), parameters.orderBySql());
}
if (parameters.isLimited()) {
if (parameters.hasLimit()) {
sqlBuilder.append(parameters.limitSql());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), parameters.limitSql());
}
@@ -87,6 +87,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.staff.data.StaffData;
import org.apache.fineract.portfolio.account.PortfolioAccountType;
@@ -279,6 +280,7 @@ public class LoansApiResource {
private final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService;
private final DefaultToApiJsonSerializer<LoanDelinquencyTagHistoryData> jsonSerializerTagHistory;
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
private final SqlValidator sqlValidator;
/*
* This template API is used for loan approval, ideally this should be invoked on loan that are pending for
@@ -476,6 +478,10 @@ public class LoansApiResource {
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(accountNo);
sqlValidator.validate(externalId);
final SearchParameters searchParameters = SearchParameters.builder().accountNo(accountNo).sortOrder(sortOrder)
.externalId(externalId).offset(offset).limit(limit).orderBy(orderBy).status(status).build();
@@ -349,19 +349,19 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
arrayPos = arrayPos + 1;
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -35,6 +35,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.data.DepositAccountOnHoldTransactionData;
import org.apache.fineract.portfolio.savings.service.DepositAccountOnHoldTransactionReadPlatformService;
@@ -50,6 +51,7 @@ public class DepositAccountOnHoldFundTransactionsApiResource {
private final DefaultToApiJsonSerializer<DepositAccountOnHoldTransactionData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final DepositAccountOnHoldTransactionReadPlatformService depositAccountOnHoldTransactionReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -60,7 +62,10 @@ public class DepositAccountOnHoldFundTransactionsApiResource {
this.context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
final Page<DepositAccountOnHoldTransactionData> transfers = this.depositAccountOnHoldTransactionReadPlatformService
.retriveAll(savingsId, guarantorFundingId, searchParameters);
@@ -69,6 +69,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
import org.apache.fineract.portfolio.savings.DepositAccountType;
@@ -105,6 +106,7 @@ public class FixedDepositAccountsApiResource {
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final FixedDepositAccountInterestCalculationService fixedDepositAccountInterestCalculationService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -144,7 +146,10 @@ public class FixedDepositAccountsApiResource {
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME);
final PaginationParameters paginationParameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final PaginationParameters paginationParameters = PaginationParameters.builder().paged(Boolean.TRUE.equals(paged)).limit(limit)
.offset(offset).orderBy(orderBy).sortOrder(sortOrder).build();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (paginationParameters.isPaged()) {
@@ -67,6 +67,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
@@ -98,6 +99,7 @@ public class RecurringDepositAccountsApiResource {
private final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService;
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -138,7 +140,10 @@ public class RecurringDepositAccountsApiResource {
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME);
final PaginationParameters paginationParameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final PaginationParameters paginationParameters = PaginationParameters.builder().paged(Boolean.TRUE.equals(paged)).limit(limit)
.offset(offset).orderBy(orderBy).sortOrder(sortOrder).build();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (paginationParameters.isPaged()) {
@@ -65,6 +65,7 @@ import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
@@ -92,6 +93,7 @@ public class SavingsAccountsApiResource {
private final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService;
private final BulkImportWorkbookService bulkImportWorkbookService;
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
private final SqlValidator sqlValidator;
@GET
@Path("template")
@@ -134,7 +136,11 @@ public class SavingsAccountsApiResource {
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forSavings(externalId, offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(externalId);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
.orderBy(orderBy).sortOrder(sortOrder).build();
final Page<SavingsAccountData> products = savingsAccountReadPlatformService.retrieveAll(searchParameters);
@@ -60,19 +60,19 @@ public class DepositAccountOnHoldTransactionReadPlatformServiceImpl implements D
paramObj.add(guarantorFundingId);
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -217,19 +217,19 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
objectArray[arrayPos] = searchParameters.getOfficeId();
arrayPos = arrayPos + 1;
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -69,6 +69,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
private final ReadWriteNonCoreDataService datatableService;
private final DataTableValidator dataTableValidator;
private final JdbcTemplate jdbcTemplate;
private final SearchUtil searchUtil;
@Override
public Page<SavingsAccountTransactionData> searchTransactions(@NotNull Long savingsId,
@@ -76,7 +77,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
context.authenticatedUser().validateHasReadPermission(SAVINGS_ACCOUNT_RESOURCE_NAME);
String apptable = EntityTables.SAVINGS_TRANSACTION.getApptableName();
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil
.mapHeadersToName(genericDataService.fillResultsetColumnHeaders(apptable));
PageRequest pageable = searchParameters.getPageable();
@@ -84,7 +85,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
if (pageable.getSort().isSorted()) {
List<Sort.Order> orders = pageable.getSort().toList();
sortPageable = pageable.withSort(Sort.by(orders.stream()
.map(e -> e.withProperty(SearchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList()));
.map(e -> e.withProperty(searchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList()));
} else {
pageable = pageable.withSort(Sort.Direction.DESC, "transaction_date", CREATED_DATE_DB_FIELD, "id");
sortPageable = pageable;
@@ -108,7 +109,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
String alias = "tr";
StringBuilder where = new StringBuilder();
ArrayList<Object> params = new ArrayList<>();
SearchUtil.buildQueryCondition(columnFilters, where, params, alias, headersByName, null, null, null, false, sqlGenerator);
searchUtil.buildQueryCondition(columnFilters, where, params, alias, headersByName, null, null, null, false, sqlGenerator);
SavingsAccountReadPlatformServiceImpl.SavingsAccountTransactionsMapper tm = new SavingsAccountReadPlatformServiceImpl.SavingsAccountTransactionsMapper();
Object[] args = params.toArray();
@@ -185,8 +186,8 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
dataTableValidator.validateTableSearch(queryRequest);
List<ResultsetColumnHeaderData> columnHeaders = genericDataService.fillResultsetColumnHeaders(apptable);
Map<String, ResultsetColumnHeaderData> headersByName = SearchUtil.mapHeadersToName(columnHeaders);
String pkColumn = SearchUtil.getFiltered(columnHeaders, ResultsetColumnHeaderData::getIsColumnPrimaryKey).getColumnName();
Map<String, ResultsetColumnHeaderData> headersByName = searchUtil.mapHeadersToName(columnHeaders);
String pkColumn = searchUtil.getFiltered(columnHeaders, ResultsetColumnHeaderData::getIsColumnPrimaryKey).getColumnName();
AdvancedQueryData baseQuery = queryRequest.getBaseQuery();
List<TableQueryData> datatableQueries = queryRequest.getDatatableQueries();
@@ -200,9 +201,9 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
selectColumns = new ArrayList<>();
} else {
columnFilters = baseQuery.getNonNullFilters();
columnFilters.forEach(e -> e.setColumn(SearchUtil.validateToJdbcColumnName(e.getColumn(), headersByName, false)));
columnFilters.forEach(e -> e.setColumn(searchUtil.validateToJdbcColumnName(e.getColumn(), headersByName, false)));
resultColumns = baseQuery.getNonNullResultColumns();
selectColumns = new ArrayList<>(SearchUtil.validateToJdbcColumnNames(resultColumns, headersByName, true));
selectColumns = new ArrayList<>(searchUtil.validateToJdbcColumnNames(resultColumns, headersByName, true));
}
columnFilters.add(0, ColumnFilterData.eq("savings_account_id", savingsId.toString()));
if (resultColumns.isEmpty() && !queryRequest.hasResultColumn()) {
@@ -214,7 +215,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
if (pageable.getSort().isSorted()) {
List<Sort.Order> orders = pageable.getSort().toList();
sortPageable = pageable.withSort(Sort.by(orders.stream()
.map(e -> e.withProperty(SearchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList()));
.map(e -> e.withProperty(searchUtil.validateToJdbcColumnName(e.getProperty(), headersByName, false))).toList()));
} else {
pageable = pageable.withSort(Sort.Direction.DESC, pkColumn);
sortPageable = pageable;
@@ -228,7 +229,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
StringBuilder from = new StringBuilder(" ").append(sqlGenerator.buildFrom(apptable, alias, false));
StringBuilder where = new StringBuilder();
ArrayList<Object> params = new ArrayList<>();
SearchUtil.buildQueryCondition(columnFilters, where, params, alias, headersByName, dateFormat, dateTimeFormat, locale, false,
searchUtil.buildQueryCondition(columnFilters, where, params, alias, headersByName, dateFormat, dateTimeFormat, locale, false,
sqlGenerator);
if (datatableQueries != null) {
@@ -280,7 +281,7 @@ public class SavingsAccountTransactionsSearchServiceImpl implements SavingsAccou
SqlRowSet rowSet = jdbcTemplate.queryForRowSet(query.toString(), args);
while (rowSet.next()) {
SearchUtil.extractJsonResult(rowSet, selectColumns, resultColumns, results);
searchUtil.extractJsonResult(rowSet, selectColumns, resultColumns, results);
}
return PageableExecutionUtils.getPage(results, pageable, () -> totalElements);
}
@@ -33,7 +33,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.DataTableValidator;
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
import org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl;
import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataService;
import org.apache.fineract.infrastructure.entityaccess.service.FineractEntityAccessUtil;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -138,6 +138,7 @@ import org.apache.fineract.portfolio.savings.service.SavingsSchedularInterestPos
import org.apache.fineract.portfolio.savings.service.SavingsSchedularInterestPosterTask;
import org.apache.fineract.portfolio.savings.service.search.SavingsAccountTransactionSearchService;
import org.apache.fineract.portfolio.savings.service.search.SavingsAccountTransactionsSearchServiceImpl;
import org.apache.fineract.portfolio.search.service.SearchUtil;
import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -151,10 +152,10 @@ public class SavingsConfiguration {
@Bean
@ConditionalOnMissingBean(SavingsAccountTransactionSearchService.class)
public SavingsAccountTransactionSearchService savingsAccountTransactionSearchService(PlatformSecurityContext context,
GenericDataService genericDataService, DatabaseSpecificSQLGenerator sqlGenerator,
ReadWriteNonCoreDataServiceImpl datatableService, DataTableValidator dataTableValidator, JdbcTemplate jdbcTemplate) {
GenericDataService genericDataService, DatabaseSpecificSQLGenerator sqlGenerator, ReadWriteNonCoreDataService datatableService,
DataTableValidator dataTableValidator, JdbcTemplate jdbcTemplate, SearchUtil searchUtil) {
return new SavingsAccountTransactionsSearchServiceImpl(context, genericDataService, sqlGenerator, datatableService,
dataTableValidator, jdbcTemplate);
dataTableValidator, jdbcTemplate, searchUtil);
}
@Bean
@@ -74,20 +74,20 @@ public class ShareAccountDividendReadPlatformServiceImpl implements ShareAccount
sqlBuilder.append(" and sa.account_no = ? ");
params.add(searchParameters.getAccountNo());
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -40,6 +40,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountDividendData;
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountDividendReadPlatformService;
import org.apache.fineract.portfolio.shareproducts.data.ShareProductDividendPayOutData;
@@ -60,6 +61,7 @@ public class ShareDividendApiResource {
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final ShareAccountDividendReadPlatformService shareAccountDividendReadPlatformService;
private final ShareProductDividendReadPlatformService shareProductDividendReadPlatformService;
private final SqlValidator sqlValidator;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@@ -69,7 +71,10 @@ public class ShareDividendApiResource {
@QueryParam("sortOrder") final String sortOrder, @QueryParam("status") final Integer status) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build();
Page<ShareProductDividendPayOutData> dividendPayoutDetails = this.shareProductDividendReadPlatformService.retriveAll(productId,
status, searchParameters);
return this.toApiJsonSerializer.serialize(dividendPayoutDetails);
@@ -85,8 +90,11 @@ public class ShareDividendApiResource {
@PathParam("productId") final Long productId) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final SearchParameters searchParameters = SearchParameters.forPaginationAndAccountNumberSearch(offset, limit, orderBy, sortOrder,
accountNo);
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
sqlValidator.validate(accountNo);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).accountNo(accountNo).build();
Page<ShareAccountDividendData> dividendDetails = this.shareAccountDividendReadPlatformService.retriveAll(dividendId,
searchParameters);
return this.toApiAccountDetailJsonSerializer.serialize(dividendDetails);
@@ -62,19 +62,19 @@ public class ShareProductDividendReadPlatformServiceImpl implements ShareProduct
sqlBuilder.append(" and pod.status = ?");
params.add(status);
}
if (searchParameters.isOrderByRequested()) {
if (searchParameters.hasOrderBy()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
if (searchParameters.hasSortOrder()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
if (searchParameters.hasLimit()) {
sqlBuilder.append(" ");
if (searchParameters.isOffset()) {
if (searchParameters.hasOffset()) {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit(), searchParameters.getOffset()));
} else {
sqlBuilder.append(sqlGenerator.limit(searchParameters.getLimit()));
@@ -179,6 +179,101 @@ fineract.module.investor.enabled=${FINERACT_MODULE_INVESTOR_ENABLED:true}
fineract.insecure-http-client=${FINERACT_INSECURE_HTTP_CLIENT:true}
# sql validation
# inject-blind
fineract.sql-validation.patterns[0].name=inject-blind
fineract.sql-validation.patterns[0].pattern=(?i).*[\\"'`]?\\s*[and|or]+\\s*[\\"'`]?([\\d\\w])+[\\"'`]?\\s*=\\s*[\\"'`]?(\\1)[\\"'`]?\\s*.*
# detect-entry-point
fineract.sql-validation.patterns[1].name=detect-entry-point
fineract.sql-validation.patterns[1].pattern=(?i)^[\\"'`]?[\\)\\s]+
# inject-timing
fineract.sql-validation.patterns[2].name=inject-timing
fineract.sql-validation.patterns[2].pattern=(?i).*[\\"'`]?\\s*[and|\\+|&|\\|]+.*\\s*[sleep|pg_sleep|benchmark]+\\s*(\\(\\s*\\d+\\s*[,]?\\s*.*\\s*\\))+.*
# detect-backend
fineract.sql-validation.patterns[3].name=detect-backend
fineract.sql-validation.patterns[3].pattern=(?i).*\\[\\s*\\"(\\w+\\(.*\\))=(\\1)\\"\\s*,\\s*\\"\\w+\\"\\s*\\].*
# detect-column
fineract.sql-validation.patterns[4].name=detect-column
fineract.sql-validation.patterns[4].pattern=(?i).*[\\"'`]?\\s*(order\\s*by|group\\s*by|union\\s*select)+\\s+([\\d+|null]?\\s*,*\\s*)+\\s*.*
# detect-out-of-bands
fineract.sql-validation.patterns[5].name=detect-out-of-bands
fineract.sql-validation.patterns[5].pattern=(?i).*(select)+\\s+(load_file)+.*
# inject-stacked-query
fineract.sql-validation.patterns[6].name=inject-stacked-query
fineract.sql-validation.patterns[6].pattern=(?i).*[;]+\\s*(create|drop|alter|truncate|comment|select|insert|update|delete|merge|upsert|call|exec)+.*(from|into|set|table|column|database)*.*
# inject-comment
fineract.sql-validation.patterns[7].name=inject-comment
fineract.sql-validation.patterns[7].pattern=(?i).*\\s+(-|/\\*|#|\\(\\{)++.*
# main
fineract.sql-validation.profiles[0].name=main
fineract.sql-validation.profiles[0].description=Main Query Validation Profile
fineract.sql-validation.profiles[0].patternRefs[0].name=inject-blind
fineract.sql-validation.profiles[0].patternRefs[0].order=0
fineract.sql-validation.profiles[0].patternRefs[1].name=detect-entry-point
fineract.sql-validation.profiles[0].patternRefs[1].order=1
fineract.sql-validation.profiles[0].patternRefs[2].name=inject-timing
fineract.sql-validation.profiles[0].patternRefs[2].order=2
fineract.sql-validation.profiles[0].patternRefs[3].name=detect-backend
fineract.sql-validation.profiles[0].patternRefs[3].order=3
fineract.sql-validation.profiles[0].patternRefs[4].name=detect-column
fineract.sql-validation.profiles[0].patternRefs[4].order=4
fineract.sql-validation.profiles[0].patternRefs[5].name=detect-out-of-bands
fineract.sql-validation.profiles[0].patternRefs[5].order=5
fineract.sql-validation.profiles[0].patternRefs[6].name=inject-stacked-query
fineract.sql-validation.profiles[0].patternRefs[6].order=6
fineract.sql-validation.profiles[0].patternRefs[7].name=inject-comment
fineract.sql-validation.profiles[0].patternRefs[7].order=7
fineract.sql-validation.profiles[0].enabled=true
# adhoc
fineract.sql-validation.profiles[1].name=adhoc
fineract.sql-validation.profiles[1].description=Adhoc Query Validation Profile
fineract.sql-validation.profiles[1].patternRefs[0].name=inject-blind
fineract.sql-validation.profiles[1].patternRefs[0].order=0
fineract.sql-validation.profiles[1].patternRefs[1].name=detect-entry-point
fineract.sql-validation.profiles[1].patternRefs[1].order=1
fineract.sql-validation.profiles[1].patternRefs[2].name=inject-timing
fineract.sql-validation.profiles[1].patternRefs[2].order=2
fineract.sql-validation.profiles[1].patternRefs[3].name=detect-backend
fineract.sql-validation.profiles[1].patternRefs[3].order=3
fineract.sql-validation.profiles[1].patternRefs[4].name=detect-column
fineract.sql-validation.profiles[1].patternRefs[4].order=4
fineract.sql-validation.profiles[1].patternRefs[5].name=detect-out-of-bands
fineract.sql-validation.profiles[1].patternRefs[5].order=5
fineract.sql-validation.profiles[1].patternRefs[6].name=inject-stacked-query
fineract.sql-validation.profiles[1].patternRefs[6].order=6
fineract.sql-validation.profiles[1].patternRefs[7].name=inject-comment
fineract.sql-validation.profiles[1].patternRefs[7].order=7
fineract.sql-validation.profiles[1].enabled=true
# dynamic
fineract.sql-validation.profiles[2].name=column
fineract.sql-validation.profiles[2].description=Column Validation Profile
fineract.sql-validation.profiles[2].patternRefs[0].name=inject-blind
fineract.sql-validation.profiles[2].patternRefs[0].order=0
fineract.sql-validation.profiles[2].patternRefs[1].name=detect-entry-point
fineract.sql-validation.profiles[2].patternRefs[1].order=1
fineract.sql-validation.profiles[2].patternRefs[2].name=inject-timing
fineract.sql-validation.profiles[2].patternRefs[2].order=2
fineract.sql-validation.profiles[2].patternRefs[3].name=detect-backend
fineract.sql-validation.profiles[2].patternRefs[3].order=3
fineract.sql-validation.profiles[2].patternRefs[4].name=detect-out-of-bands
fineract.sql-validation.profiles[2].patternRefs[4].order=4
fineract.sql-validation.profiles[2].patternRefs[5].name=inject-stacked-query
fineract.sql-validation.profiles[2].patternRefs[5].order=5
fineract.sql-validation.profiles[2].patternRefs[6].name=inject-comment
fineract.sql-validation.profiles[2].patternRefs[6].order=6
fineract.sql-validation.profiles[2].enabled=true
# Logging pattern for the console
logging.pattern.console=${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(%replace([%X{correlationId}]){'\\[\\]', ''}) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}}
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]