Improve error handling if reporting service implementation is missing [FINERACT-1173]
This commit is contained in:
committed by
Petri Tuomola
parent
a3ab467278
commit
b96061613b
+8
-3
@@ -51,6 +51,7 @@ import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSeria
|
|||||||
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
|
import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService;
|
import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService;
|
||||||
|
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
@@ -71,17 +72,19 @@ public class ReportsApiResource {
|
|||||||
private final ReadReportingService readReportingService;
|
private final ReadReportingService readReportingService;
|
||||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||||
|
private final ReportingProcessServiceProvider reportingProcessServiceProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReportsApiResource(final PlatformSecurityContext context, final ReadReportingService readReportingService,
|
public ReportsApiResource(final PlatformSecurityContext context, final ReadReportingService readReportingService,
|
||||||
final ToApiJsonSerializer<ReportData> toApiJsonSerializer,
|
final ToApiJsonSerializer<ReportData> toApiJsonSerializer,
|
||||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||||
final ApiRequestParameterHelper apiRequestParameterHelper) {
|
final ApiRequestParameterHelper apiRequestParameterHelper, ReportingProcessServiceProvider reportingProcessServiceProvider) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.readReportingService = readReportingService;
|
this.readReportingService = readReportingService;
|
||||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||||
|
this.reportingProcessServiceProvider = reportingProcessServiceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@@ -117,7 +120,8 @@ public class ReportsApiResource {
|
|||||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
|
||||||
if (settings.isTemplate()) {
|
if (settings.isTemplate()) {
|
||||||
result.appendedTemplate(this.readReportingService.getAllowedParameters(), this.readReportingService.getAllowedReportTypes());
|
result.appendedTemplate(this.readReportingService.getAllowedParameters(),
|
||||||
|
this.reportingProcessServiceProvider.findAllReportingTypes());
|
||||||
}
|
}
|
||||||
return this.toApiJsonSerializer.serialize(settings, result, this.responseDataParameters);
|
return this.toApiJsonSerializer.serialize(settings, result, this.responseDataParameters);
|
||||||
}
|
}
|
||||||
@@ -135,7 +139,8 @@ public class ReportsApiResource {
|
|||||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||||
|
|
||||||
final ReportData result = new ReportData();
|
final ReportData result = new ReportData();
|
||||||
result.appendedTemplate(this.readReportingService.getAllowedParameters(), this.readReportingService.getAllowedReportTypes());
|
result.appendedTemplate(this.readReportingService.getAllowedParameters(),
|
||||||
|
this.reportingProcessServiceProvider.findAllReportingTypes());
|
||||||
|
|
||||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
return this.toApiJsonSerializer.serialize(settings, result, this.responseDataParameters);
|
return this.toApiJsonSerializer.serialize(settings, result, this.responseDataParameters);
|
||||||
|
|||||||
+14
-98
@@ -25,10 +25,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DefaultValue;
|
import javax.ws.rs.DefaultValue;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@@ -40,20 +36,14 @@ import javax.ws.rs.core.Context;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
|
||||||
import javax.ws.rs.core.StreamingOutput;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
|
import org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
|
|
||||||
import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
|
|
||||||
import org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
|
|
||||||
import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService;
|
import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService;
|
||||||
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
|
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
|
||||||
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
|
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
|
||||||
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
|
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
|
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
@@ -65,20 +55,17 @@ import org.springframework.stereotype.Component;
|
|||||||
@Tag(name = "Run Reports", description = "")
|
@Tag(name = "Run Reports", description = "")
|
||||||
public class RunreportsApiResource {
|
public class RunreportsApiResource {
|
||||||
|
|
||||||
|
public static final String IS_SELF_SERVICE_USER_REPORT_PARAMETER = "isSelfServiceUserReport";
|
||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final ToApiJsonSerializer<ReportData> toApiJsonSerializer;
|
|
||||||
private final ReadReportingService readExtraDataAndReportingService;
|
private final ReadReportingService readExtraDataAndReportingService;
|
||||||
private final GenericDataService genericDataService;
|
|
||||||
private final ReportingProcessServiceProvider reportingProcessServiceProvider;
|
private final ReportingProcessServiceProvider reportingProcessServiceProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public RunreportsApiResource(final PlatformSecurityContext context, final ReadReportingService readExtraDataAndReportingService,
|
public RunreportsApiResource(final PlatformSecurityContext context, final ReadReportingService readExtraDataAndReportingService,
|
||||||
final GenericDataService genericDataService, final ToApiJsonSerializer<ReportData> toApiJsonSerializer,
|
|
||||||
final ReportingProcessServiceProvider reportingProcessServiceProvider) {
|
final ReportingProcessServiceProvider reportingProcessServiceProvider) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.readExtraDataAndReportingService = readExtraDataAndReportingService;
|
this.readExtraDataAndReportingService = readExtraDataAndReportingService;
|
||||||
this.genericDataService = genericDataService;
|
|
||||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
|
||||||
this.reportingProcessServiceProvider = reportingProcessServiceProvider;
|
this.reportingProcessServiceProvider = reportingProcessServiceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,79 +95,26 @@ public class RunreportsApiResource {
|
|||||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = RunreportsApiResourceSwagger.RunReportsResponse.class))) })
|
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = RunreportsApiResourceSwagger.RunReportsResponse.class))) })
|
||||||
public Response runReport(@PathParam("reportName") @Parameter(description = "reportName") final String reportName,
|
public Response runReport(@PathParam("reportName") @Parameter(description = "reportName") final String reportName,
|
||||||
@Context final UriInfo uriInfo,
|
@Context final UriInfo uriInfo,
|
||||||
@DefaultValue("false") @QueryParam("isSelfServiceUserReport") @Parameter(description = "isSelfServiceUserReport") final boolean isSelfServiceUserReport) {
|
@DefaultValue("false") @QueryParam(IS_SELF_SERVICE_USER_REPORT_PARAMETER) @Parameter(description = IS_SELF_SERVICE_USER_REPORT_PARAMETER) final boolean isSelfServiceUserReport) {
|
||||||
|
|
||||||
final MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
|
final MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
|
||||||
|
final boolean parameterType = ApiParameterHelper.parameterType(queryParams);
|
||||||
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
|
||||||
final boolean exportCsv = ApiParameterHelper.exportCsv(uriInfo.getQueryParameters());
|
|
||||||
final boolean parameterType = ApiParameterHelper.parameterType(uriInfo.getQueryParameters());
|
|
||||||
final boolean exportPdf = ApiParameterHelper.exportPdf(uriInfo.getQueryParameters());
|
|
||||||
|
|
||||||
checkUserPermissionForReport(reportName, parameterType);
|
checkUserPermissionForReport(reportName, parameterType);
|
||||||
|
|
||||||
String parameterTypeValue = null;
|
// Pass through isSelfServiceUserReport so that ReportingProcessService implementations can use it
|
||||||
if (!parameterType) {
|
queryParams.putSingle(IS_SELF_SERVICE_USER_REPORT_PARAMETER, Boolean.toString(isSelfServiceUserReport));
|
||||||
parameterTypeValue = "report";
|
|
||||||
String reportType = this.readExtraDataAndReportingService.getReportType(reportName, isSelfServiceUserReport);
|
String reportType = this.readExtraDataAndReportingService.getReportType(reportName, isSelfServiceUserReport);
|
||||||
ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType);
|
ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType);
|
||||||
if (reportingProcessService != null) {
|
if (reportingProcessService == null) {
|
||||||
return reportingProcessService.processRequest(reportName, queryParams);
|
throw new PlatformServiceUnavailableException("err.msg.report.service.implementation.missing",
|
||||||
}
|
ReportingProcessServiceProvider.SERVICE_MISSING + reportType, reportType);
|
||||||
} else {
|
|
||||||
parameterTypeValue = "parameter";
|
|
||||||
}
|
}
|
||||||
|
return reportingProcessService.processRequest(reportName, queryParams);
|
||||||
// PDF format
|
|
||||||
|
|
||||||
if (exportPdf) {
|
|
||||||
final Map<String, String> reportParams = getReportParams(queryParams);
|
|
||||||
final String pdfFileName = this.readExtraDataAndReportingService.retrieveReportPDF(reportName, parameterTypeValue, reportParams,
|
|
||||||
isSelfServiceUserReport);
|
|
||||||
|
|
||||||
final File file = new File(pdfFileName);
|
|
||||||
|
|
||||||
final ResponseBuilder response = Response.ok(file);
|
|
||||||
response.header("Content-Disposition", "attachment; filename=\"" + pdfFileName + "\"");
|
|
||||||
response.header("content-Type", "application/pdf");
|
|
||||||
|
|
||||||
return response.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!exportCsv) {
|
|
||||||
final Map<String, String> reportParams = getReportParams(queryParams);
|
|
||||||
|
|
||||||
final GenericResultsetData result = this.readExtraDataAndReportingService.retrieveGenericResultset(reportName,
|
|
||||||
parameterTypeValue, reportParams, isSelfServiceUserReport);
|
|
||||||
|
|
||||||
String json = "";
|
|
||||||
final boolean genericResultSetIsPassed = ApiParameterHelper.genericResultSetPassed(uriInfo.getQueryParameters());
|
|
||||||
final boolean genericResultSet = ApiParameterHelper.genericResultSet(uriInfo.getQueryParameters());
|
|
||||||
if (genericResultSetIsPassed) {
|
|
||||||
if (genericResultSet) {
|
|
||||||
json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
|
|
||||||
} else {
|
|
||||||
json = this.genericDataService.generateJsonFromGenericResultsetData(result);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response.ok().entity(json).type(MediaType.APPLICATION_JSON).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// CSV Export
|
|
||||||
final Map<String, String> reportParams = getReportParams(queryParams);
|
|
||||||
final StreamingOutput result = this.readExtraDataAndReportingService.retrieveReportCSV(reportName, parameterTypeValue, reportParams,
|
|
||||||
isSelfServiceUserReport);
|
|
||||||
|
|
||||||
return Response.ok().entity(result).type("text/csv")
|
|
||||||
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".csv").build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkUserPermissionForReport(final String reportName, final boolean parameterType) {
|
private void checkUserPermissionForReport(final String reportName, final boolean parameterType) {
|
||||||
|
|
||||||
// Anyone can run a 'report' that is simply getting possible parameter
|
// Anyone can run a 'report' that is simply getting possible parameter
|
||||||
// (dropdown listbox) values.
|
// (dropdown listbox) values.
|
||||||
if (!parameterType) {
|
if (!parameterType) {
|
||||||
@@ -190,22 +124,4 @@ public class RunreportsApiResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> getReportParams(final MultivaluedMap<String, String> queryParams) {
|
|
||||||
|
|
||||||
final Map<String, String> reportParams = new HashMap<>();
|
|
||||||
final Set<String> keys = queryParams.keySet();
|
|
||||||
String pKey;
|
|
||||||
String pValue;
|
|
||||||
for (final String k : keys) {
|
|
||||||
|
|
||||||
if (k.startsWith("R_")) {
|
|
||||||
pKey = "${" + k.substring(2) + "}";
|
|
||||||
pValue = queryParams.get(k).get(0);
|
|
||||||
SQLInjectionValidator.validateSQLInput(pValue);
|
|
||||||
reportParams.put(pKey, pValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reportParams;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* 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.dataqueries.service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
import javax.ws.rs.core.StreamingOutput;
|
||||||
|
import org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
|
||||||
|
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||||
|
import org.apache.fineract.infrastructure.dataqueries.api.RunreportsApiResource;
|
||||||
|
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
|
||||||
|
import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
|
||||||
|
import org.apache.fineract.infrastructure.report.annotation.ReportService;
|
||||||
|
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@ReportService(type = { "Table", "Chart", "SMS" })
|
||||||
|
public class DatatableReportingProcessService implements ReportingProcessService {
|
||||||
|
|
||||||
|
private final ReadReportingService readExtraDataAndReportingService;
|
||||||
|
private final ToApiJsonSerializer<ReportData> toApiJsonSerializer;
|
||||||
|
private final GenericDataService genericDataService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public DatatableReportingProcessService(final ReadReportingService readExtraDataAndReportingService,
|
||||||
|
final GenericDataService genericDataService, final ToApiJsonSerializer<ReportData> toApiJsonSerializer) {
|
||||||
|
this.readExtraDataAndReportingService = readExtraDataAndReportingService;
|
||||||
|
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||||
|
this.genericDataService = genericDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response processRequest(String reportName, MultivaluedMap<String, String> queryParams) {
|
||||||
|
boolean isSelfServiceUserReport = Boolean.parseBoolean(
|
||||||
|
queryParams.getOrDefault(RunreportsApiResource.IS_SELF_SERVICE_USER_REPORT_PARAMETER, List.of("false")).get(0));
|
||||||
|
final boolean prettyPrint = ApiParameterHelper.prettyPrint(queryParams);
|
||||||
|
final boolean exportCsv = ApiParameterHelper.exportCsv(queryParams);
|
||||||
|
final boolean exportPdf = ApiParameterHelper.exportPdf(queryParams);
|
||||||
|
final String parameterTypeValue = ApiParameterHelper.parameterType(queryParams) ? "parameter" : "report";
|
||||||
|
|
||||||
|
// PDF format
|
||||||
|
if (exportPdf) {
|
||||||
|
final Map<String, String> reportParams = getReportParams(queryParams);
|
||||||
|
final String pdfFileName = this.readExtraDataAndReportingService.retrieveReportPDF(reportName, parameterTypeValue, reportParams,
|
||||||
|
isSelfServiceUserReport);
|
||||||
|
|
||||||
|
final File file = new File(pdfFileName);
|
||||||
|
|
||||||
|
final ResponseBuilder response = Response.ok(file);
|
||||||
|
response.header("Content-Disposition", "attachment; filename=\"" + pdfFileName + "\"");
|
||||||
|
response.header("content-Type", "application/pdf");
|
||||||
|
|
||||||
|
return response.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON format
|
||||||
|
if (!exportCsv) {
|
||||||
|
final Map<String, String> reportParams = getReportParams(queryParams);
|
||||||
|
|
||||||
|
final GenericResultsetData result = this.readExtraDataAndReportingService.retrieveGenericResultset(reportName,
|
||||||
|
parameterTypeValue, reportParams, isSelfServiceUserReport);
|
||||||
|
|
||||||
|
String json;
|
||||||
|
final boolean genericResultSetIsPassed = ApiParameterHelper.genericResultSetPassed(queryParams);
|
||||||
|
final boolean genericResultSet = ApiParameterHelper.genericResultSet(queryParams);
|
||||||
|
if (genericResultSetIsPassed) {
|
||||||
|
if (genericResultSet) {
|
||||||
|
json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
|
||||||
|
} else {
|
||||||
|
json = this.genericDataService.generateJsonFromGenericResultsetData(result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
json = this.toApiJsonSerializer.serializePretty(prettyPrint, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.ok().entity(json).type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSV format
|
||||||
|
final Map<String, String> reportParams = getReportParams(queryParams);
|
||||||
|
final StreamingOutput result = this.readExtraDataAndReportingService.retrieveReportCSV(reportName, parameterTypeValue, reportParams,
|
||||||
|
isSelfServiceUserReport);
|
||||||
|
|
||||||
|
return Response.ok().entity(result).type("text/csv")
|
||||||
|
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".csv").build();
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
-16
@@ -30,29 +30,28 @@ import org.apache.fineract.useradministration.domain.AppUser;
|
|||||||
|
|
||||||
public interface ReadReportingService {
|
public interface ReadReportingService {
|
||||||
|
|
||||||
|
Collection<ReportData> retrieveReportList();
|
||||||
|
|
||||||
|
ReportData retrieveReport(Long id);
|
||||||
|
|
||||||
|
String getReportType(String reportName, boolean isSelfServiceUserReport);
|
||||||
|
|
||||||
|
Collection<ReportParameterData> getAllowedParameters();
|
||||||
|
|
||||||
|
// TODO Move the following x3 methods into the (new; FINERACT-1173) DatatableReportingProcessService?
|
||||||
|
|
||||||
|
String retrieveReportPDF(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
|
||||||
|
|
||||||
StreamingOutput retrieveReportCSV(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
|
StreamingOutput retrieveReportCSV(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
|
||||||
|
|
||||||
GenericResultsetData retrieveGenericResultset(String name, String type, Map<String, String> extractedQueryParams,
|
GenericResultsetData retrieveGenericResultset(String name, String type, Map<String, String> extractedQueryParams,
|
||||||
boolean isSelfServiceUserReport);
|
boolean isSelfServiceUserReport);
|
||||||
|
|
||||||
String retrieveReportPDF(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
|
// TODO This is weird, could they not be using the retrieveGenericResultset() above after all?
|
||||||
|
// needed for smsCampaign and emailCampaign jobs where securityContext is null
|
||||||
String getReportType(String reportName, boolean isSelfServiceUserReport);
|
|
||||||
|
|
||||||
Collection<ReportData> retrieveReportList();
|
|
||||||
|
|
||||||
Collection<ReportParameterData> getAllowedParameters();
|
|
||||||
|
|
||||||
ReportData retrieveReport(Long id);
|
|
||||||
|
|
||||||
Collection<String> getAllowedReportTypes();
|
|
||||||
|
|
||||||
// needed for smsCampaign and emailCampaign jobs where securityContext is
|
|
||||||
// null
|
|
||||||
GenericResultsetData retrieveGenericResultSetForSmsEmailCampaign(String name, String type, Map<String, String> extractedQueryParams);
|
GenericResultsetData retrieveGenericResultSetForSmsEmailCampaign(String name, String type, Map<String, String> extractedQueryParams);
|
||||||
|
|
||||||
String sqlToRunForSmsEmailCampaign(String name, String type, Map<String, String> queryParams);
|
// TODO kill this when tackling https://issues.apache.org/jira/browse/FINERACT-1264
|
||||||
|
|
||||||
ByteArrayOutputStream generatePentahoReportAsOutputStream(String reportName, String outputTypeParam, Map<String, String> queryParams,
|
ByteArrayOutputStream generatePentahoReportAsOutputStream(String reportName, String outputTypeParam, Map<String, String> queryParams,
|
||||||
Locale locale, AppUser runReportAsUser, StringBuilder errorLog);
|
Locale locale, AppUser runReportAsUser, StringBuilder errorLog);
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-56
@@ -27,7 +27,6 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -51,7 +50,6 @@ import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeader
|
|||||||
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
|
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.exception.ReportNotFoundException;
|
import org.apache.fineract.infrastructure.dataqueries.exception.ReportNotFoundException;
|
||||||
import org.apache.fineract.infrastructure.documentmanagement.contentrepository.FileSystemContentRepository;
|
import org.apache.fineract.infrastructure.documentmanagement.contentrepository.FileSystemContentRepository;
|
||||||
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
|
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
||||||
import org.apache.fineract.infrastructure.security.utils.SQLInjectionException;
|
import org.apache.fineract.infrastructure.security.utils.SQLInjectionException;
|
||||||
@@ -74,53 +72,43 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final GenericDataService genericDataService;
|
private final GenericDataService genericDataService;
|
||||||
private final ReportingProcessServiceProvider reportingProcessServiceProvider;
|
|
||||||
private final ColumnValidator columnValidator;
|
private final ColumnValidator columnValidator;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReadReportingServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
|
public ReadReportingServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
|
||||||
final GenericDataService genericDataService, final ReportingProcessServiceProvider reportingProcessServiceProvider,
|
final GenericDataService genericDataService, final ColumnValidator columnValidator) {
|
||||||
final ColumnValidator columnValidator) {
|
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
|
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
|
||||||
this.genericDataService = genericDataService;
|
this.genericDataService = genericDataService;
|
||||||
this.reportingProcessServiceProvider = reportingProcessServiceProvider;
|
|
||||||
this.columnValidator = columnValidator;
|
this.columnValidator = columnValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamingOutput retrieveReportCSV(final String name, final String type, final Map<String, String> queryParams,
|
public StreamingOutput retrieveReportCSV(final String name, final String type, final Map<String, String> queryParams,
|
||||||
final boolean isSelfServiceUserReport) {
|
final boolean isSelfServiceUserReport) {
|
||||||
|
return out -> {
|
||||||
|
try {
|
||||||
|
|
||||||
return new StreamingOutput() {
|
final GenericResultsetData result = retrieveGenericResultset(name, type, queryParams, isSelfServiceUserReport);
|
||||||
|
final StringBuilder sb = generateCsvFileBuffer(result);
|
||||||
|
|
||||||
@Override
|
final InputStream in = new ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
public void write(final OutputStream out) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
final GenericResultsetData result = retrieveGenericResultset(name, type, queryParams, isSelfServiceUserReport);
|
final byte[] outputByte = new byte[4096];
|
||||||
final StringBuilder sb = generateCsvFileBuffer(result);
|
Integer readLen = in.read(outputByte, 0, 4096);
|
||||||
|
|
||||||
final InputStream in = new ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8));
|
while (readLen != -1) {
|
||||||
|
out.write(outputByte, 0, readLen);
|
||||||
final byte[] outputByte = new byte[4096];
|
readLen = in.read(outputByte, 0, 4096);
|
||||||
Integer readLen = in.read(outputByte, 0, 4096);
|
|
||||||
|
|
||||||
while (readLen != -1) {
|
|
||||||
out.write(outputByte, 0, readLen);
|
|
||||||
readLen = in.read(outputByte, 0, 4096);
|
|
||||||
}
|
|
||||||
// in.close();
|
|
||||||
// out.flush();
|
|
||||||
// out.close();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
throw new PlatformDataIntegrityException("error.msg.exception.error", e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
// in.close();
|
||||||
|
// out.flush();
|
||||||
|
// out.close();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.exception.error", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private StringBuilder generateCsvFileBuffer(final GenericResultsetData result) {
|
private StringBuilder generateCsvFileBuffer(final GenericResultsetData result) {
|
||||||
@@ -146,8 +134,8 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
final String doubleQuote = "\"";
|
final String doubleQuote = "\"";
|
||||||
final String twoDoubleQuotes = doubleQuote + doubleQuote;
|
final String twoDoubleQuotes = doubleQuote + doubleQuote;
|
||||||
LOG.info("NO. of Rows: {}", data.size());
|
LOG.info("NO. of Rows: {}", data.size());
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (ResultsetRowData element : data) {
|
||||||
row = data.get(i).getRow();
|
row = element.getRow();
|
||||||
rSize = row.size();
|
rSize = row.size();
|
||||||
for (int j = 0; j < rSize; j++) {
|
for (int j = 0; j < rSize; j++) {
|
||||||
// currCol = columnHeaders.get(j).getColumnName();
|
// currCol = columnHeaders.get(j).getColumnName();
|
||||||
@@ -184,7 +172,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
final GenericResultsetData result = this.genericDataService.fillGenericResultSet(sql);
|
final GenericResultsetData result = this.genericDataService.fillGenericResultSet(sql);
|
||||||
|
|
||||||
final long elapsed = System.currentTimeMillis() - startTime;
|
final long elapsed = System.currentTimeMillis() - startTime;
|
||||||
LOG.info("FINISHING Report/Request Name: {} - {} Elapsed Time: {}", new Object[] { name, type, elapsed });
|
LOG.info("FINISHING Report/Request Name: {} - {} Elapsed Time: {}", name, type, elapsed);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,11 +201,9 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
sql = this.genericDataService.wrapSQL(sql);
|
sql = this.genericDataService.wrapSQL(sql);
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getSql(final String name, final String type) {
|
private String getSql(final String name, final String type) {
|
||||||
|
|
||||||
final String inputSql = "select " + type + "_sql as the_sql from stretchy_" + type + " where " + type + "_name = '" + name + "'";
|
final String inputSql = "select " + type + "_sql as the_sql from stretchy_" + type + " where " + type + "_name = '" + name + "'";
|
||||||
validateReportName(name);
|
validateReportName(name);
|
||||||
|
|
||||||
@@ -234,7 +220,6 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getReportType(final String reportName, final boolean isSelfServiceUserReport) {
|
public String getReportType(final String reportName, final boolean isSelfServiceUserReport) {
|
||||||
|
|
||||||
final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName
|
final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName
|
||||||
+ "' and self_service_user_report = ?";
|
+ "' and self_service_user_report = ?";
|
||||||
validateReportName(reportName);
|
validateReportName(reportName);
|
||||||
@@ -242,7 +227,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
|
|
||||||
final String sqlWrapped = this.genericDataService.wrapSQL(sql);
|
final String sqlWrapped = this.genericDataService.wrapSQL(sql);
|
||||||
|
|
||||||
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped, new Object[] { isSelfServiceUserReport });
|
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped, isSelfServiceUserReport);
|
||||||
|
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
return rs.getString("report_type");
|
return rs.getString("report_type");
|
||||||
@@ -290,8 +275,8 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
String currColType;
|
String currColType;
|
||||||
String currVal;
|
String currVal;
|
||||||
LOG.info("NO. of Rows: {}", data.size());
|
LOG.info("NO. of Rows: {}", data.size());
|
||||||
for (int i = 0; i < data.size(); i++) {
|
for (ResultsetRowData element : data) {
|
||||||
row = data.get(i).getRow();
|
row = element.getRow();
|
||||||
rSize = row.size();
|
rSize = row.size();
|
||||||
for (int j = 0; j < rSize; j++) {
|
for (int j = 0; j < rSize; j++) {
|
||||||
currColType = columnHeaders.get(j).getColumnType();
|
currColType = columnHeaders.get(j).getColumnType();
|
||||||
@@ -338,7 +323,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
|
|
||||||
final String sql = rm.schema(id);
|
final String sql = rm.schema(id);
|
||||||
|
|
||||||
final Collection<ReportParameterJoinData> rpJoins = this.jdbcTemplate.query(sql, rm, new Object[] {});
|
final Collection<ReportParameterJoinData> rpJoins = this.jdbcTemplate.query(sql, rm);
|
||||||
|
|
||||||
final Collection<ReportData> reportList = new ArrayList<>();
|
final Collection<ReportData> reportList = new ArrayList<>();
|
||||||
if (rpJoins == null || rpJoins.size() == 0) {
|
if (rpJoins == null || rpJoins.size() == 0) {
|
||||||
@@ -410,22 +395,12 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<ReportParameterData> getAllowedParameters() {
|
public Collection<ReportParameterData> getAllowedParameters() {
|
||||||
|
|
||||||
final ReportParameterMapper rm = new ReportParameterMapper();
|
final ReportParameterMapper rm = new ReportParameterMapper();
|
||||||
final String sql = rm.schema();
|
final String sql = rm.schema();
|
||||||
final Collection<ReportParameterData> parameters = this.jdbcTemplate.query(sql, rm, new Object[] {});
|
final Collection<ReportParameterData> parameters = this.jdbcTemplate.query(sql, rm);
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getAllowedReportTypes() {
|
|
||||||
final List<String> reportTypes = new ArrayList<>();
|
|
||||||
reportTypes.add("Table");
|
|
||||||
reportTypes.add("Chart");
|
|
||||||
reportTypes.addAll(this.reportingProcessServiceProvider.findAllReportingTypes());
|
|
||||||
return reportTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ReportParameterJoinMapper implements RowMapper<ReportParameterJoinData> {
|
private static final class ReportParameterJoinMapper implements RowMapper<ReportParameterJoinData> {
|
||||||
|
|
||||||
public String schema(final Long reportId) {
|
public String schema(final Long reportId) {
|
||||||
@@ -460,7 +435,6 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReportParameterJoinData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
|
public ReportParameterJoinData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
|
||||||
|
|
||||||
final Long reportId = rs.getLong("reportId");
|
final Long reportId = rs.getLong("reportId");
|
||||||
final String reportName = rs.getString("reportName");
|
final String reportName = rs.getString("reportName");
|
||||||
final String reportType = rs.getString("reportType");
|
final String reportType = rs.getString("reportType");
|
||||||
@@ -491,9 +465,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
private static final class ReportParameterMapper implements RowMapper<ReportParameterData> {
|
private static final class ReportParameterMapper implements RowMapper<ReportParameterData> {
|
||||||
|
|
||||||
public String schema() {
|
public String schema() {
|
||||||
|
|
||||||
return "select p.id as id, p.parameter_name as parameterName from stretchy_parameter p where ifnull(p.special,'') != 'Y' order by p.id";
|
return "select p.id as id, p.parameter_name as parameterName from stretchy_parameter p where ifnull(p.special,'') != 'Y' order by p.id";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -516,12 +488,11 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
final GenericResultsetData result = this.genericDataService.fillGenericResultSet(sql);
|
final GenericResultsetData result = this.genericDataService.fillGenericResultSet(sql);
|
||||||
|
|
||||||
final long elapsed = System.currentTimeMillis() - startTime;
|
final long elapsed = System.currentTimeMillis() - startTime;
|
||||||
LOG.info("FINISHING Report/Request Name: {} - {} Elapsed Time: {}", new Object[] { name, type, elapsed });
|
LOG.info("FINISHING Report/Request Name: {} - {} Elapsed Time: {}", name, type, elapsed);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private String sqlToRunForSmsEmailCampaign(final String name, final String type, final Map<String, String> queryParams) {
|
||||||
public String sqlToRunForSmsEmailCampaign(final String name, final String type, final Map<String, String> queryParams) {
|
|
||||||
String sql = getSql(name, type);
|
String sql = getSql(name, type);
|
||||||
|
|
||||||
final Set<String> keys = queryParams.keySet();
|
final Set<String> keys = queryParams.keySet();
|
||||||
@@ -599,7 +570,6 @@ public class ReadReportingServiceImpl implements ReadReportingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateReportName(final String name) {
|
private void validateReportName(final String name) {
|
||||||
|
|
||||||
if (!StringUtils.isBlank(name) && !name.matches(REPORT_NAME_REGEX_PATTERN)) {
|
if (!StringUtils.isBlank(name) && !name.matches(REPORT_NAME_REGEX_PATTERN)) {
|
||||||
throw new SQLInjectionException();
|
throw new SQLInjectionException();
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -39,6 +39,7 @@ import org.apache.fineract.infrastructure.dataqueries.domain.ReportRepository;
|
|||||||
import org.apache.fineract.infrastructure.dataqueries.exception.ReportNotFoundException;
|
import org.apache.fineract.infrastructure.dataqueries.exception.ReportNotFoundException;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.exception.ReportParameterNotFoundException;
|
import org.apache.fineract.infrastructure.dataqueries.exception.ReportParameterNotFoundException;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.serialization.ReportCommandFromApiJsonDeserializer;
|
import org.apache.fineract.infrastructure.dataqueries.serialization.ReportCommandFromApiJsonDeserializer;
|
||||||
|
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.useradministration.domain.Permission;
|
import org.apache.fineract.useradministration.domain.Permission;
|
||||||
import org.apache.fineract.useradministration.domain.PermissionRepository;
|
import org.apache.fineract.useradministration.domain.PermissionRepository;
|
||||||
@@ -62,20 +63,20 @@ public class ReportWritePlatformServiceImpl implements ReportWritePlatformServic
|
|||||||
private final ReportParameterUsageRepository reportParameterUsageRepository;
|
private final ReportParameterUsageRepository reportParameterUsageRepository;
|
||||||
private final ReportParameterRepository reportParameterRepository;
|
private final ReportParameterRepository reportParameterRepository;
|
||||||
private final PermissionRepository permissionRepository;
|
private final PermissionRepository permissionRepository;
|
||||||
private final ReadReportingService readReportingService;
|
private final ReportingProcessServiceProvider reportingProcessServiceProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReportWritePlatformServiceImpl(final PlatformSecurityContext context,
|
public ReportWritePlatformServiceImpl(final PlatformSecurityContext context,
|
||||||
final ReportCommandFromApiJsonDeserializer fromApiJsonDeserializer, final ReportRepository reportRepository,
|
final ReportCommandFromApiJsonDeserializer fromApiJsonDeserializer, final ReportRepository reportRepository,
|
||||||
final ReportParameterRepository reportParameterRepository, final ReportParameterUsageRepository reportParameterUsageRepository,
|
final ReportParameterRepository reportParameterRepository, final ReportParameterUsageRepository reportParameterUsageRepository,
|
||||||
final PermissionRepository permissionRepository, final ReadReportingService readReportingService) {
|
final PermissionRepository permissionRepository, final ReportingProcessServiceProvider reportingProcessServiceProvider) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||||
this.reportRepository = reportRepository;
|
this.reportRepository = reportRepository;
|
||||||
this.reportParameterRepository = reportParameterRepository;
|
this.reportParameterRepository = reportParameterRepository;
|
||||||
this.reportParameterUsageRepository = reportParameterUsageRepository;
|
this.reportParameterUsageRepository = reportParameterUsageRepository;
|
||||||
this.permissionRepository = permissionRepository;
|
this.permissionRepository = permissionRepository;
|
||||||
this.readReportingService = readReportingService;
|
this.reportingProcessServiceProvider = reportingProcessServiceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -87,7 +88,7 @@ public class ReportWritePlatformServiceImpl implements ReportWritePlatformServic
|
|||||||
|
|
||||||
this.fromApiJsonDeserializer.validate(command.json());
|
this.fromApiJsonDeserializer.validate(command.json());
|
||||||
|
|
||||||
final Report report = Report.fromJson(command, this.readReportingService.getAllowedReportTypes());
|
final Report report = Report.fromJson(command, this.reportingProcessServiceProvider.findAllReportingTypes());
|
||||||
final Set<ReportParameterUsage> reportParameterUsages = assembleSetOfReportParameterUsages(report, command);
|
final Set<ReportParameterUsage> reportParameterUsages = assembleSetOfReportParameterUsages(report, command);
|
||||||
report.update(reportParameterUsages);
|
report.update(reportParameterUsages);
|
||||||
|
|
||||||
@@ -121,7 +122,7 @@ public class ReportWritePlatformServiceImpl implements ReportWritePlatformServic
|
|||||||
|
|
||||||
final Report report = this.reportRepository.findById(reportId).orElseThrow(() -> new ReportNotFoundException(reportId));
|
final Report report = this.reportRepository.findById(reportId).orElseThrow(() -> new ReportNotFoundException(reportId));
|
||||||
|
|
||||||
final Map<String, Object> changes = report.update(command, this.readReportingService.getAllowedReportTypes());
|
final Map<String, Object> changes = report.update(command, this.reportingProcessServiceProvider.findAllReportingTypes());
|
||||||
|
|
||||||
if (changes.containsKey("reportParameters")) {
|
if (changes.containsKey("reportParameters")) {
|
||||||
final Set<ReportParameterUsage> reportParameterUsages = assembleSetOfReportParameterUsages(report, command);
|
final Set<ReportParameterUsage> reportParameterUsages = assembleSetOfReportParameterUsages(report, command);
|
||||||
|
|||||||
+1
-1
@@ -32,5 +32,5 @@ public @interface ReportService {
|
|||||||
/**
|
/**
|
||||||
* @return the type of the report
|
* @return the type of the report
|
||||||
*/
|
*/
|
||||||
String type();
|
String[] type();
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-41
@@ -18,68 +18,46 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.infrastructure.report.provider;
|
package org.apache.fineract.infrastructure.report.provider;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import org.apache.fineract.infrastructure.report.annotation.ReportService;
|
import org.apache.fineract.infrastructure.report.annotation.ReportService;
|
||||||
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
|
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Scope("singleton")
|
@Scope("singleton")
|
||||||
public class ReportingProcessServiceProvider implements ApplicationContextAware {
|
public class ReportingProcessServiceProvider {
|
||||||
|
|
||||||
|
public static final String SERVICE_MISSING = "There is no ReportingProcessService registered in the ReportingProcessServiceProvider for this report type: ";
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReportingProcessServiceProvider.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ReportingProcessServiceProvider.class);
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
private final Map<String, ReportingProcessService> reportingProcessServices;
|
||||||
|
|
||||||
Map<String, String> reportingProcessServices = null;
|
|
||||||
|
|
||||||
ReportingProcessServiceProvider() {
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ReportingProcessServiceProvider(List<ReportingProcessService> reportingProcessServices) {
|
||||||
|
var mapBuilder = ImmutableMap.<String, ReportingProcessService>builder();
|
||||||
|
for (ReportingProcessService s : reportingProcessServices) {
|
||||||
|
String[] reportTypes = s.getClass().getAnnotation(ReportService.class).type();
|
||||||
|
for (String type : reportTypes) {
|
||||||
|
mapBuilder.put(type, s);
|
||||||
|
}
|
||||||
|
LOGGER.info("Registered report service '{}' for type/s '{}'", s, reportTypes);
|
||||||
|
}
|
||||||
|
this.reportingProcessServices = mapBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReportingProcessService findReportingProcessService(final String reportType) {
|
public ReportingProcessService findReportingProcessService(final String reportType) {
|
||||||
if (this.reportingProcessServices.containsKey(reportType)) {
|
return reportingProcessServices.getOrDefault(reportType, null);
|
||||||
return (ReportingProcessService) this.applicationContext.getBean(this.reportingProcessServices.get(reportType));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
this.initializeRegistry();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> findAllReportingTypes() {
|
public Collection<String> findAllReportingTypes() {
|
||||||
return this.reportingProcessServices.keySet();
|
return this.reportingProcessServices.keySet();
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeRegistry() {
|
|
||||||
if (this.reportingProcessServices == null) {
|
|
||||||
this.reportingProcessServices = new HashMap<>();
|
|
||||||
|
|
||||||
final String[] reportServiceBeans = this.applicationContext.getBeanNamesForAnnotation(ReportService.class);
|
|
||||||
if (ArrayUtils.isNotEmpty(reportServiceBeans)) {
|
|
||||||
for (final String reportName : reportServiceBeans) {
|
|
||||||
LOGGER.info("Register report service '{}' ...", reportName);
|
|
||||||
final ReportService service = this.applicationContext.findAnnotationOnBean(reportName, ReportService.class);
|
|
||||||
try {
|
|
||||||
this.reportingProcessServices.put(service.type(), reportName);
|
|
||||||
} catch (final Throwable th) {
|
|
||||||
LOGGER.error("Unable to register reporting service '{}'!", reportName, th);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -18,11 +18,28 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.infrastructure.report.service;
|
package org.apache.fineract.infrastructure.report.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
|
||||||
|
|
||||||
public interface ReportingProcessService {
|
public interface ReportingProcessService {
|
||||||
|
|
||||||
Response processRequest(String reportName, MultivaluedMap<String, String> queryParams);
|
Response processRequest(String reportName, MultivaluedMap<String, String> queryParams);
|
||||||
|
|
||||||
|
default Map<String, String> getReportParams(final MultivaluedMap<String, String> queryParams) {
|
||||||
|
final Map<String, String> reportParams = new HashMap<>();
|
||||||
|
final Set<String> keys = queryParams.keySet();
|
||||||
|
for (final String k : keys) {
|
||||||
|
if (k.startsWith("R_")) {
|
||||||
|
String pKey = "${" + k.substring(2) + "}";
|
||||||
|
String pValue = queryParams.get(k).get(0);
|
||||||
|
SQLInjectionValidator.validateSQLInput(pValue);
|
||||||
|
reportParams.put(pKey, pValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reportParams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -471,7 +471,7 @@ public class ReportMailingJobWritePlatformServiceImpl implements ReportMailingJo
|
|||||||
errorLog.append("Response object entity is not equal to ByteArrayOutputStream ---------- ");
|
errorLog.append("Response object entity is not equal to ByteArrayOutputStream ---------- ");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorLog.append("ReportingProcessService object is null ---------- ");
|
errorLog.append(ReportingProcessServiceProvider.SERVICE_MISSING + reportType);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
errorLog.append("The ReportMailingJobWritePlatformServiceImpl.generateReportOutputStream method threw an Exception: " + e
|
errorLog.append("The ReportMailingJobWritePlatformServiceImpl.generateReportOutputStream method threw an Exception: " + e
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ public class ReportsTest extends IntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
void runExpectedPaymentsPentahoReportWithoutPlugin() {
|
void runExpectedPaymentsPentahoReportWithoutPlugin() {
|
||||||
assertThat(fineract().reportsRun.runReportGetFile("Expected Payments By Date - Formatted", Map.of("R_endDate", "2013-04-30",
|
assertThat(fineract().reportsRun.runReportGetFile("Expected Payments By Date - Formatted", Map.of("R_endDate", "2013-04-30",
|
||||||
"R_loanOfficerId", "-1", "R_officeId", "1", "R_startDate", "2013-04-16", "output-type", "PDF"), false)).hasHttpStatus(404);
|
"R_loanOfficerId", "-1", "R_officeId", "1", "R_startDate", "2013-04-16", "output-type", "PDF"), false)).hasHttpStatus(503);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user