add facility for restricting data scope for reports

This commit is contained in:
John Woodlock
2012-08-27 11:00:04 +10:00
parent 58a6568efc
commit 03f8a0fcc0
2 changed files with 23 additions and 54 deletions
@@ -14,7 +14,6 @@ public interface ReadExtraDataAndReportingService {
StreamingOutput retrieveReportCSV(String name, String type, StreamingOutput retrieveReportCSV(String name, String type,
Map<String, String> extractedQueryParams); Map<String, String> extractedQueryParams);
// @PreAuthorize(value = "hasAnyRole('REPORTING_SUPER_USER_ROLE')")
GenericResultsetData retrieveGenericResultset(String name, String type, GenericResultsetData retrieveGenericResultset(String name, String type,
Map<String, String> extractedQueryParams); Map<String, String> extractedQueryParams);
@@ -29,6 +29,7 @@ import org.mifosng.platform.exceptions.AdditionalFieldsNotFoundException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
import org.mifosng.platform.exceptions.ReportNotFoundException; import org.mifosng.platform.exceptions.ReportNotFoundException;
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot; import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.MasterReport; import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException; import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
@@ -51,6 +52,8 @@ import org.springframework.stereotype.Service;
public class ReadExtraDataAndReportingServiceImpl implements public class ReadExtraDataAndReportingServiceImpl implements
ReadExtraDataAndReportingService { ReadExtraDataAndReportingService {
private final PlatformSecurityContext context;
private final static Logger logger = LoggerFactory private final static Logger logger = LoggerFactory
.getLogger(ReadExtraDataAndReportingServiceImpl.class); .getLogger(ReadExtraDataAndReportingServiceImpl.class);
@@ -58,12 +61,13 @@ public class ReadExtraDataAndReportingServiceImpl implements
private Boolean noPentaho = false; private Boolean noPentaho = false;
@Autowired @Autowired
public ReadExtraDataAndReportingServiceImpl( public ReadExtraDataAndReportingServiceImpl(final PlatformSecurityContext context,
final TenantAwareRoutingDataSource dataSource) { final TenantAwareRoutingDataSource dataSource) {
// kick off pentaho reports server // kick off pentaho reports server
ClassicEngineBoot.getInstance().start(); ClassicEngineBoot.getInstance().start();
noPentaho = false; noPentaho = false;
this.context = context;
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@@ -157,21 +161,10 @@ public class ReadExtraDataAndReportingServiceImpl implements
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
logger.info("STARTING REPORT: " + name + " Type: " + type); logger.info("STARTING REPORT: " + name + " Type: " + type);
// AppUser currentUser = extractAuthenticatedUser();
// Collection<GrantedAuthority> permissions =
// currentUser.getAuthorities();
/*
* AppUser currentUser = extractAuthenticatedUser(); Boolean validUser =
* verifyUserDetails(currentUser);
*
* if (!validUser) { return null; }
*
* String orgId = currentUser.getOrganisation().getId().toString(); put
* back in later
*/
String sql; String sql;
if (name.equals(".")) { if (name.equals(".")) {
// this is to support api /reports - which isn't that important a
// call and isn't used in the default reporting UI
sql = "select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category," sql = "select r.report_id, r.report_name, r.report_type, r.report_subtype, r.report_category,"
+ " rp.parameter_id, rp.report_parameter_name, p.parameter_name" + " rp.parameter_id, rp.report_parameter_name, p.parameter_name"
+ " from stretchy_report r" + " from stretchy_report r"
@@ -227,7 +220,8 @@ public class ReadExtraDataAndReportingServiceImpl implements
return new GenericResultsetData(columnHeaders, resultsetDataRows); return new GenericResultsetData(columnHeaders, resultsetDataRows);
} catch (SQLException e) { } catch (SQLException e) {
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), "Sql: " + sql); throw new PlatformDataIntegrityException("error.msg.sql.error",
e.getMessage(), "Sql: " + sql);
} finally { } finally {
dbClose(db_statement, db_connection); dbClose(db_statement, db_connection);
} }
@@ -250,6 +244,9 @@ public class ReadExtraDataAndReportingServiceImpl implements
sql = replace(sql, key, pValue); sql = replace(sql, key, pValue);
} }
//Allowing the sql query to restrict data by office hierarchy if it is required
sql = replace(sql, "${currentHierarchy}", context.authenticatedUser().getOffice().getHierarchy());
// wrap sql to prevent JDBC sql errors and also prevent malicious sql // wrap sql to prevent JDBC sql errors and also prevent malicious sql
sql = "select x.* from (" + sql + ") x"; sql = "select x.* from (" + sql + ") x";
@@ -257,35 +254,6 @@ public class ReadExtraDataAndReportingServiceImpl implements
} }
// private Boolean verifyUserDetails(AppUser usr) {
//
// // some logs to be taken out after testing
// String idDetails = usr.getId() + ", " + usr.getLastname() + ", "
// + usr.getFirstname();
// logger.info("Id: " + idDetails + " Organisation: "
// + usr.getOrganisation().getId() + " Office: "
// + usr.getOffice().getId() + " Role Names: "
// + usr.getRoleNames());
// String otherDetails = "Head Officer User? " + usr.isHeadOfficeUser()
// + " Enabled: " + usr.isEnabled();
// logger.info(otherDetails);
// if (usr.getAuthorities() != null) {
// // for (GrantedAuthority grantedAuthority : usr.getAuthorities()) {
// // logger.info("Granted Authority: " +
// // grantedAuthority.getAuthority());
// // }
// }
// logger.info("");
//
// // some checks
// if (usr.getOrganisation().getId() == null) {
// logger.info("Organisation ID not Found");
// return false;
// }
//
// return true;
// }
private String getReportSql(String reportName) { private String getReportSql(String reportName) {
String sql = "select report_sql as the_sql from stretchy_report where report_name = '" String sql = "select report_sql as the_sql from stretchy_report where report_name = '"
+ reportName + "'"; + reportName + "'";
@@ -465,7 +433,8 @@ public class ReadExtraDataAndReportingServiceImpl implements
return result; return result;
} }
private GenericResultsetData fillExtraDataGenericResultSet(final String type, final String set, final Long id) { private GenericResultsetData fillExtraDataGenericResultSet(
final String type, final String set, final Long id) {
Connection db_connection = null; Connection db_connection = null;
Statement db_statement1 = null; Statement db_statement1 = null;
@@ -785,7 +754,8 @@ public class ReadExtraDataAndReportingServiceImpl implements
db_connection = null; db_connection = null;
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), "Error closing database connection"); throw new PlatformDataIntegrityException("error.msg.sql.error",
e.getMessage(), "Error closing database connection");
} }
} }