From f7ecc139f947b5aacb6a8d6744d17b71b091bf13 Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sun, 21 Mar 2021 12:38:58 +0300 Subject: [PATCH 01/11] FINERACT-854 Use prepared statements instead of string concatenated SQL everywhere PART 1 --- .../ProvisioningEntriesReadPlatformServiceImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java index 69ec7286566..89059b110dd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java @@ -58,26 +58,26 @@ public ProvisioningEntriesReadPlatformServiceImpl(final RoutingDataSource dataSo public Collection retrieveLoanProductsProvisioningData(Date date) { String formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(date); formattedDate = "'" + formattedDate + "'"; - LoanProductProvisioningEntryMapper mapper = new LoanProductProvisioningEntryMapper(formattedDate); + LoanProductProvisioningEntryMapper mapper = new LoanProductProvisioningEntryMapper(); final String sql = mapper.schema(); - return this.jdbcTemplate.query(sql, mapper, new Object[] {}); + return this.jdbcTemplate.query(sql, mapper, new Object[] {formattedDate, formattedDate, formattedDate}); } private static final class LoanProductProvisioningEntryMapper implements RowMapper { private final StringBuilder sqlQuery; - private LoanProductProvisioningEntryMapper(String formattedDate) { + private LoanProductProvisioningEntryMapper() { sqlQuery = new StringBuilder().append( "select if(loan.loan_type_enum=1, mclient.office_id, mgroup.office_id) as office_id, loan.loan_type_enum, pcd.criteria_id as criteriaid, loan.product_id,loan.currency_code,") - .append("GREATEST(datediff(").append(formattedDate) + .append("GREATEST(datediff(?") .append(",sch.duedate),0) as numberofdaysoverdue,sch.duedate, pcd.category_id, pcd.provision_percentage,") .append("loan.total_outstanding_derived as outstandingbalance, pcd.liability_account, pcd.expense_account from m_loan_repayment_schedule sch") .append(" LEFT JOIN m_loan loan on sch.loan_id = loan.id") .append(" JOIN m_loanproduct_provisioning_mapping lpm on lpm.product_id = loan.product_id") .append(" JOIN m_provisioning_criteria_definition pcd on pcd.criteria_id = lpm.criteria_id and ") - .append("(pcd.min_age <= GREATEST(datediff(").append(formattedDate).append(",sch.duedate),0) and ") - .append("GREATEST(datediff(").append(formattedDate).append(",sch.duedate),0) <= pcd.max_age) and ") + .append("(pcd.min_age <= GREATEST(datediff(?").append(",sch.duedate),0) and ") + .append("GREATEST(datediff(?").append(",sch.duedate),0) <= pcd.max_age) and ") .append("pcd.criteria_id is not null ").append("LEFT JOIN m_client mclient ON mclient.id = loan.client_id ") .append("LEFT JOIN m_group mgroup ON mgroup.id = loan.group_id ") .append("where loan.loan_status_id=300 and sch.duedate = ") From be27862e939157087f8d3d83e08b4b357cd07a1e Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sun, 21 Mar 2021 13:28:07 +0300 Subject: [PATCH 02/11] Use prepared statements instead of string concatenated SQL everywhere - WIP (FINERACT-854) --- .../service/GenericDataServiceImpl.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java index 8c11f880e49..b75df1f3ce5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java @@ -261,9 +261,9 @@ private List retreiveColumnValues(final String codeNam final List columnValues = new ArrayList<>(); final String sql = "select v.id, v.code_score, v.code_value from m_code m " + " join m_code_value v on v.code_id = m.id " - + " where m.code_name = '" + codeName + "' order by v.order_position, v.id"; + + " where m.code_name = ? order by v.order_position, v.id"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql); + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] {codeName}); rsValues.beforeFirst(); while (rsValues.next()) { @@ -281,9 +281,9 @@ private List retreiveColumnValues(final Integer codeId final List columnValues = new ArrayList<>(); if (codeId != null) { - final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =" + codeId + final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =?" + " order by v.order_position, v.id"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql); + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, Integer.class, new Object[] {codeId}); rsValues.beforeFirst(); while (rsValues.next()) { final Integer id = rsValues.getInt("id"); @@ -298,10 +298,10 @@ private List retreiveColumnValues(final Integer codeId private SqlRowSet getDatatableMetaData(final String datatable) { final String sql = "select COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMN_KEY" - + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = '" + datatable - + "'order by ORDINAL_POSITION"; + + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = ?" + + " order by ORDINAL_POSITION"; - final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql); + final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] {datatable}); if (columnDefinitions.next()) { return columnDefinitions; } @@ -309,11 +309,10 @@ private SqlRowSet getDatatableMetaData(final String datatable) { throw new DatatableNotFoundException(datatable); } - private SqlRowSet getDatatableCodeData(final String datatable, final String columnName) { - - final String sql = "select mc.id,mc.code_name from m_code mc join x_table_column_code_mappings xcc on xcc.code_id = mc.id where xcc.column_alias_name='" - + datatable.toLowerCase().replaceAll("\\s", "_") + "_" + columnName + "'"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql); + private SqlRowSet getDatatableCodeData(final String aDatatable, final String aColumnName) { + String datatableColumnName = aDatatable.toLowerCase().replaceAll("\\s", "_") + "_" + aColumnName; + final String sql = "select mc.id,mc.code_name from m_code mc join x_table_column_code_mappings xcc on xcc.code_id = mc.id where xcc.column_alias_name=?"; + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] {datatableColumnName}); return rsValues; } From 95cf1308cd4d1288501cfb1772512e536f77e253 Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sun, 21 Mar 2021 14:07:47 +0300 Subject: [PATCH 03/11] Fix format (FINERACT-854) --- ...sioningEntriesReadPlatformServiceImpl.java | 8 +++--- .../service/EmailReadPlatformServiceImpl.java | 25 ++++++++----------- .../ConfigurationReadPlatformServiceImpl.java | 5 ++-- .../service/GenericDataServiceImpl.java | 14 +++++------ 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java index 89059b110dd..2d19a685598 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java @@ -60,7 +60,7 @@ public Collection retrieveLoanProductsProvisio formattedDate = "'" + formattedDate + "'"; LoanProductProvisioningEntryMapper mapper = new LoanProductProvisioningEntryMapper(); final String sql = mapper.schema(); - return this.jdbcTemplate.query(sql, mapper, new Object[] {formattedDate, formattedDate, formattedDate}); + return this.jdbcTemplate.query(sql, mapper, new Object[] { formattedDate, formattedDate, formattedDate }); } private static final class LoanProductProvisioningEntryMapper implements RowMapper { @@ -76,9 +76,9 @@ private LoanProductProvisioningEntryMapper() { .append(" LEFT JOIN m_loan loan on sch.loan_id = loan.id") .append(" JOIN m_loanproduct_provisioning_mapping lpm on lpm.product_id = loan.product_id") .append(" JOIN m_provisioning_criteria_definition pcd on pcd.criteria_id = lpm.criteria_id and ") - .append("(pcd.min_age <= GREATEST(datediff(?").append(",sch.duedate),0) and ") - .append("GREATEST(datediff(?").append(",sch.duedate),0) <= pcd.max_age) and ") - .append("pcd.criteria_id is not null ").append("LEFT JOIN m_client mclient ON mclient.id = loan.client_id ") + .append("(pcd.min_age <= GREATEST(datediff(?").append(",sch.duedate),0) and ").append("GREATEST(datediff(?") + .append(",sch.duedate),0) <= pcd.max_age) and ").append("pcd.criteria_id is not null ") + .append("LEFT JOIN m_client mclient ON mclient.id = loan.client_id ") .append("LEFT JOIN m_group mgroup ON mgroup.id = loan.group_id ") .append("where loan.loan_status_id=300 and sch.duedate = ") .append("(select MIN(sch1.duedate) from m_loan_repayment_schedule sch1 where sch1.loan_id=loan.id and sch1.completed_derived=false)"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java index 7465a48e2be..126a404256d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java @@ -130,46 +130,41 @@ public EmailData retrieveOne(final Long resourceId) { @Override public Collection retrieveAllPending(final SearchParameters searchParameters) { final String sqlPlusLimit = (searchParameters.getLimit() > 0) ? " limit 0, " + searchParameters.getLimit() : ""; - final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = " - + EmailMessageStatusType.PENDING.getValue() + sqlPlusLimit; + final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = " + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] {}); + return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.PENDING.getValue() }); } @Override public Collection retrieveAllSent(final SearchParameters searchParameters) { final String sqlPlusLimit = (searchParameters.getLimit() > 0) ? " limit 0, " + searchParameters.getLimit() : ""; - final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = " + EmailMessageStatusType.SENT.getValue() - + sqlPlusLimit; + final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = ?" + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] {}); + return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.SENT.getValue() }); } @Override public List retrieveExternalIdsOfAllSent(final Integer limit) { final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : ""; - final String sql = "select external_id from " + this.emailRowMapper.tableName() + " where status_enum = " - + EmailMessageStatusType.SENT.getValue() + sqlPlusLimit; + final String sql = "select external_id from " + this.emailRowMapper.tableName() + " where status_enum = " + sqlPlusLimit; - return this.jdbcTemplate.queryForList(sql, Long.class); + return this.jdbcTemplate.queryForList(sql, Long.class, new Object[] { EmailMessageStatusType.SENT.getValue() }); } @Override public Collection retrieveAllDelivered(final Integer limit) { final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : ""; - final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = " - + EmailMessageStatusType.DELIVERED.getValue() + sqlPlusLimit; + final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = ?" + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] {}); + return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.DELIVERED.getValue() }); } @Override public Collection retrieveAllFailed(final SearchParameters searchParameters) { final String sqlPlusLimit = (searchParameters.getLimit() > 0) ? " limit 0, " + searchParameters.getLimit() : ""; - final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = " + EmailMessageStatusType.FAILED.getValue() - + sqlPlusLimit; + final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = ?" + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] {}); + return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.FAILED.getValue() }); } @Override diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java index 1034401ded7..d41a0207819 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java @@ -56,12 +56,13 @@ public GlobalConfigurationData retrieveGlobalConfiguration(final boolean survey) if (survey) { sql += " JOIN x_registered_table on x_registered_table.registered_table_name = c.name "; - sql += " WHERE x_registered_table.category =" + DataTableApiConstant.CATEGORY_PPI; + sql += " WHERE x_registered_table.category = ?"; } sql += " order by c.id"; - final List globalConfiguration = this.jdbcTemplate.query(sql, this.rm, new Object[] {}); + final List globalConfiguration = this.jdbcTemplate.query(sql, this.rm, + new Object[] { DataTableApiConstant.CATEGORY_PPI }); return new GlobalConfigurationData(globalConfiguration); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java index b75df1f3ce5..3341389795c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java @@ -263,7 +263,7 @@ private List retreiveColumnValues(final String codeNam final String sql = "select v.id, v.code_score, v.code_value from m_code m " + " join m_code_value v on v.code_id = m.id " + " where m.code_name = ? order by v.order_position, v.id"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] {codeName}); + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { codeName }); rsValues.beforeFirst(); while (rsValues.next()) { @@ -281,9 +281,8 @@ private List retreiveColumnValues(final Integer codeId final List columnValues = new ArrayList<>(); if (codeId != null) { - final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =?" - + " order by v.order_position, v.id"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, Integer.class, new Object[] {codeId}); + final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =?" + " order by v.order_position, v.id"; + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, Integer.class, new Object[] { codeId }); rsValues.beforeFirst(); while (rsValues.next()) { final Integer id = rsValues.getInt("id"); @@ -298,10 +297,9 @@ private List retreiveColumnValues(final Integer codeId private SqlRowSet getDatatableMetaData(final String datatable) { final String sql = "select COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMN_KEY" - + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = ?" - + " order by ORDINAL_POSITION"; + + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = ?" + " order by ORDINAL_POSITION"; - final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] {datatable}); + final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { datatable }); if (columnDefinitions.next()) { return columnDefinitions; } @@ -312,7 +310,7 @@ private SqlRowSet getDatatableMetaData(final String datatable) { private SqlRowSet getDatatableCodeData(final String aDatatable, final String aColumnName) { String datatableColumnName = aDatatable.toLowerCase().replaceAll("\\s", "_") + "_" + aColumnName; final String sql = "select mc.id,mc.code_name from m_code mc join x_table_column_code_mappings xcc on xcc.code_id = mc.id where xcc.column_alias_name=?"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] {datatableColumnName}); + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { datatableColumnName }); return rsValues; } From 3856b18c5c7c3f44e072f4d055ffd31cd6af575b Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sat, 27 Mar 2021 17:15:46 +0300 Subject: [PATCH 04/11] Use prepared statements instead of string concatenated SQL everywhere - WIP (FINERACT-854) --- .../service/ConfigurationReadPlatformServiceImpl.java | 2 +- .../dataqueries/service/GenericDataServiceImpl.java | 4 ++-- .../core_db/V365__reportCategoryList-FINERACT-1306.sql | 9 +++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java index d41a0207819..65eaec1f7dd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java @@ -62,7 +62,7 @@ public GlobalConfigurationData retrieveGlobalConfiguration(final boolean survey) sql += " order by c.id"; final List globalConfiguration = this.jdbcTemplate.query(sql, this.rm, - new Object[] { DataTableApiConstant.CATEGORY_PPI }); + survey ? new Object[] { DataTableApiConstant.CATEGORY_PPI } : new Object[] {}); return new GlobalConfigurationData(globalConfiguration); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java index 3341389795c..078d3d3e049 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java @@ -281,7 +281,7 @@ private List retreiveColumnValues(final Integer codeId final List columnValues = new ArrayList<>(); if (codeId != null) { - final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =?" + " order by v.order_position, v.id"; + final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =? order by v.order_position, v.id"; final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, Integer.class, new Object[] { codeId }); rsValues.beforeFirst(); while (rsValues.next()) { @@ -297,7 +297,7 @@ private List retreiveColumnValues(final Integer codeId private SqlRowSet getDatatableMetaData(final String datatable) { final String sql = "select COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMN_KEY" - + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = ?" + " order by ORDINAL_POSITION"; + + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = ? order by ORDINAL_POSITION"; final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { datatable }); if (columnDefinitions.next()) { diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql index 70ffd5df96e..23253a341a5 100644 --- a/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql @@ -18,5 +18,10 @@ -- -- two tables added: ReportCategoryList and FullReportList (FINERACT-1306) -INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report)VALUES ("ReportCategoryList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1); -INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report)VALUES ("FullReportList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1); +INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report) +SELECT "ReportCategoryList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1 +ON DUPLICATE key UPDATE report_name = 'ReportCategoryList'; + +INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report) +SELECT "FullReportList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1 +ON DUPLICATE key UPDATE report_name = 'FullReportList'; From be4e79c3a14b4cf475d16a0839908e75480ef5df Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sat, 27 Mar 2021 18:54:53 +0300 Subject: [PATCH 05/11] Use prepared statements instead of string concatenated SQL everywhere - WIP (FINERACT-854) --- .../service/GenericDataServiceImpl.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java index 078d3d3e049..8c11f880e49 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java @@ -261,9 +261,9 @@ private List retreiveColumnValues(final String codeNam final List columnValues = new ArrayList<>(); final String sql = "select v.id, v.code_score, v.code_value from m_code m " + " join m_code_value v on v.code_id = m.id " - + " where m.code_name = ? order by v.order_position, v.id"; + + " where m.code_name = '" + codeName + "' order by v.order_position, v.id"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { codeName }); + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql); rsValues.beforeFirst(); while (rsValues.next()) { @@ -281,8 +281,9 @@ private List retreiveColumnValues(final Integer codeId final List columnValues = new ArrayList<>(); if (codeId != null) { - final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =? order by v.order_position, v.id"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, Integer.class, new Object[] { codeId }); + final String sql = "select v.id, v.code_value from m_code_value v where v.code_id =" + codeId + + " order by v.order_position, v.id"; + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql); rsValues.beforeFirst(); while (rsValues.next()) { final Integer id = rsValues.getInt("id"); @@ -297,9 +298,10 @@ private List retreiveColumnValues(final Integer codeId private SqlRowSet getDatatableMetaData(final String datatable) { final String sql = "select COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMN_KEY" - + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = ? order by ORDINAL_POSITION"; + + " from INFORMATION_SCHEMA.COLUMNS " + " where TABLE_SCHEMA = schema() and TABLE_NAME = '" + datatable + + "'order by ORDINAL_POSITION"; - final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { datatable }); + final SqlRowSet columnDefinitions = this.jdbcTemplate.queryForRowSet(sql); if (columnDefinitions.next()) { return columnDefinitions; } @@ -307,10 +309,11 @@ private SqlRowSet getDatatableMetaData(final String datatable) { throw new DatatableNotFoundException(datatable); } - private SqlRowSet getDatatableCodeData(final String aDatatable, final String aColumnName) { - String datatableColumnName = aDatatable.toLowerCase().replaceAll("\\s", "_") + "_" + aColumnName; - final String sql = "select mc.id,mc.code_name from m_code mc join x_table_column_code_mappings xcc on xcc.code_id = mc.id where xcc.column_alias_name=?"; - final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql, String.class, new Object[] { datatableColumnName }); + private SqlRowSet getDatatableCodeData(final String datatable, final String columnName) { + + final String sql = "select mc.id,mc.code_name from m_code mc join x_table_column_code_mappings xcc on xcc.code_id = mc.id where xcc.column_alias_name='" + + datatable.toLowerCase().replaceAll("\\s", "_") + "_" + columnName + "'"; + final SqlRowSet rsValues = this.jdbcTemplate.queryForRowSet(sql); return rsValues; } From 18f2a68f289cc57843005a802cdb6d95e9cd0d0b Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sat, 27 Mar 2021 20:01:47 +0300 Subject: [PATCH 06/11] Use prepared statements instead of string concatenated SQL everywhere - WIP (FINERACT-854) --- .../service/ProvisioningEntriesReadPlatformServiceImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java index 2d19a685598..5396bfc9b5e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java @@ -57,7 +57,6 @@ public ProvisioningEntriesReadPlatformServiceImpl(final RoutingDataSource dataSo @Override public Collection retrieveLoanProductsProvisioningData(Date date) { String formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(date); - formattedDate = "'" + formattedDate + "'"; LoanProductProvisioningEntryMapper mapper = new LoanProductProvisioningEntryMapper(); final String sql = mapper.schema(); return this.jdbcTemplate.query(sql, mapper, new Object[] { formattedDate, formattedDate, formattedDate }); From cc4f1f7d98f7c3d021bc7359d36648f6202a5c4e Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sun, 28 Mar 2021 22:02:12 +0300 Subject: [PATCH 07/11] Fix Tenant SQLi (FINERACT-854) --- .../BasicAuthTenantDetailsServiceJdbc.java | 13 ++++---- .../service/JdbcTenantDetailsService.java | 31 ++++++++++++------- .../V6__add_unique_tenant_identifier.sql | 20 ++++++++++++ 3 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 fineract-provider/src/main/resources/sql/migrations/list_db/V6__add_unique_tenant_identifier.sql diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java index c0783d6aac1..a5c1596cd75 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java @@ -49,7 +49,7 @@ public BasicAuthTenantDetailsServiceJdbc(@Qualifier("hikariTenantDataSource") fi private static final class TenantMapper implements RowMapper { private final boolean isReport; - private final StringBuilder sqlBuilder = new StringBuilder(" t.id, ts.id as connectionId , ")// + private final StringBuilder sqlBuilder = new StringBuilder("SELECT t.id, ts.id as connectionId, ")// .append(" t.timezone_id as timezoneId , t.name,t.identifier, ts.schema_name as schemaName, ts.schema_server as schemaServer,")// .append(" ts.schema_server_port as schemaServerPort, ts.schema_connection_parameters as schemaConnectionParameters, ts.auto_update as autoUpdate,")// .append(" ts.schema_username as schemaUsername, ts.schema_password as schemaPassword , ts.pool_initial_size as initialSize,")// @@ -60,7 +60,7 @@ private static final class TenantMapper implements RowMapper { - private final StringBuilder sqlBuilder = new StringBuilder("t.id, ts.id as connectionId , ")// + private final String tenantIdentifier; + + private final StringBuilder sqlBuilder = new StringBuilder("SELECT t.id, ts.id as connectionId, ")// .append(" t.timezone_id as timezoneId , t.name,t.identifier, ts.schema_name as schemaName, ts.schema_server as schemaServer,")// .append(" ts.schema_server_port as schemaServerPort, ts.schema_connection_parameters as schemaConnectionParameters, ts.auto_update as autoUpdate,")// .append(" ts.schema_username as schemaUsername, ts.schema_password as schemaPassword , ts.pool_initial_size as initialSize,")// @@ -60,21 +62,28 @@ private static final class TenantMapper implements RowMapper findAllTenants() { - final TenantMapper rm = new TenantMapper(); - final String sql = "select " + rm.schema(); + final TenantMapper rm = new TenantMapper(null); + final String sql = rm.schema(); final List fineractPlatformTenants = this.jdbcTemplate.query(sql, rm, new Object[] {}); return fineractPlatformTenants; diff --git a/fineract-provider/src/main/resources/sql/migrations/list_db/V6__add_unique_tenant_identifier.sql b/fineract-provider/src/main/resources/sql/migrations/list_db/V6__add_unique_tenant_identifier.sql new file mode 100644 index 00000000000..f94da8fa353 --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/list_db/V6__add_unique_tenant_identifier.sql @@ -0,0 +1,20 @@ +-- +-- 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. +-- + +ALTER TABLE tenants ADD UNIQUE (identifier); From 834346613e6ea08cd082322e082f88216b242438 Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Mon, 29 Mar 2021 11:55:37 +0300 Subject: [PATCH 08/11] Fix Duplicate entry whilst issue (FINERACT-854) --- .../core_db/V365__reportCategoryList-FINERACT-1306.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql index 23253a341a5..794ab210e6f 100644 --- a/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql @@ -19,9 +19,9 @@ -- two tables added: ReportCategoryList and FullReportList (FINERACT-1306) INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report) -SELECT "ReportCategoryList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1 +SELECT 'ReportCategoryList', 'Table', NULL, NULL, NULL, 1, 1 ON DUPLICATE key UPDATE report_name = 'ReportCategoryList'; INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report) -SELECT "FullReportList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1 +SELECT 'FullReportList', 'Table', NULL, NULL, NULL, 1, 1 ON DUPLICATE key UPDATE report_name = 'FullReportList'; From 37311edb9c702ad5c9806ae44678d2600d18186f Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sun, 4 Apr 2021 15:28:24 +0300 Subject: [PATCH 09/11] Fix some reporting issues including SQLi vulnerabilities (FINERACT-854) --- .../api/RunreportsApiResource.java | 10 +++++- .../service/ReadReportingServiceImpl.java | 32 +++++-------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java index 0f0c4c5b7c3..aa9bbb80f11 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java @@ -39,6 +39,7 @@ import javax.ws.rs.core.UriInfo; import org.apache.fineract.infrastructure.core.api.ApiParameterHelper; import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException; +import org.apache.fineract.infrastructure.dataqueries.service.DatatableReportingProcessService; import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService; import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider; import org.apache.fineract.infrastructure.report.service.ReportingProcessService; @@ -60,13 +61,16 @@ public class RunreportsApiResource { private final PlatformSecurityContext context; private final ReadReportingService readExtraDataAndReportingService; private final ReportingProcessServiceProvider reportingProcessServiceProvider; + private final DatatableReportingProcessService datatableReportingProcessService; @Autowired public RunreportsApiResource(final PlatformSecurityContext context, final ReadReportingService readExtraDataAndReportingService, - final ReportingProcessServiceProvider reportingProcessServiceProvider) { + final ReportingProcessServiceProvider reportingProcessServiceProvider, + DatatableReportingProcessService aDatatableReportingProcessService) { this.context = context; this.readExtraDataAndReportingService = readExtraDataAndReportingService; this.reportingProcessServiceProvider = reportingProcessServiceProvider; + datatableReportingProcessService = aDatatableReportingProcessService; } @GET @@ -105,6 +109,10 @@ public Response runReport(@PathParam("reportName") @Parameter(description = "rep // Pass through isSelfServiceUserReport so that ReportingProcessService implementations can use it queryParams.putSingle(IS_SELF_SERVICE_USER_REPORT_PARAMETER, Boolean.toString(isSelfServiceUserReport)); + if (parameterType) { + return datatableReportingProcessService.processRequest(reportName, queryParams); + } + String reportType = this.readExtraDataAndReportingService.getReportType(reportName, isSelfServiceUserReport); ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType); if (reportingProcessService == null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java index 43584f3588e..cd538e33c79 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java @@ -38,7 +38,6 @@ import java.util.Set; import javax.sql.DataSource; import javax.ws.rs.core.StreamingOutput; -import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.core.domain.JdbcSupport; import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; import org.apache.fineract.infrastructure.core.service.RoutingDataSource; @@ -51,8 +50,6 @@ import org.apache.fineract.infrastructure.dataqueries.exception.ReportNotFoundException; import org.apache.fineract.infrastructure.documentmanagement.contentrepository.FileSystemContentRepository; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; -import org.apache.fineract.infrastructure.security.utils.ColumnValidator; -import org.apache.fineract.infrastructure.security.utils.SQLInjectionException; import org.apache.fineract.useradministration.domain.AppUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,22 +63,19 @@ public class ReadReportingServiceImpl implements ReadReportingService { private static final Logger LOG = LoggerFactory.getLogger(ReadReportingServiceImpl.class); - private static final String REPORT_NAME_REGEX_PATTERN = "^[a-zA-Z][a-zA-Z0-9\\-_\\s]{0,48}[a-zA-Z0-9\\s](\\([a-zA-Z]*\\))?$"; private final JdbcTemplate jdbcTemplate; private final DataSource dataSource; private final PlatformSecurityContext context; private final GenericDataService genericDataService; - private final ColumnValidator columnValidator; @Autowired public ReadReportingServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, - final GenericDataService genericDataService, final ColumnValidator columnValidator) { + final GenericDataService genericDataService) { this.context = context; this.dataSource = dataSource; this.jdbcTemplate = new JdbcTemplate(this.dataSource); this.genericDataService = genericDataService; - this.columnValidator = columnValidator; } @Override @@ -204,13 +198,12 @@ private String getSQLtoRun(final String name, final String type, final Map retrieveReports(final Long id) { final String sql = rm.schema(id); - final Collection rpJoins = this.jdbcTemplate.query(sql, rm); + final Collection rpJoins = this.jdbcTemplate.query(sql, rm, + id != null ? new Object[] { id } : new Object[] {}); final Collection reportList = new ArrayList<>(); if (rpJoins == null || rpJoins.size() == 0) { @@ -416,7 +407,7 @@ public String schema(final Long reportId) { sql += " from stretchy_report r" + " left join stretchy_report_parameter rp on rp.report_id = r.id" + " left join stretchy_parameter p on p.id = rp.parameter_id"; if (reportId != null) { - sql += " where r.id = " + reportId; + sql += " where r.id = ?"; } else { sql += " order by r.id, rp.parameter_id"; } @@ -498,7 +489,6 @@ private String sqlToRunForSmsEmailCampaign(final String name, final String type, final Set keys = queryParams.keySet(); for (String key : keys) { final String pValue = queryParams.get(key); - // LOG.info("(" + key + " : " + pValue + ")"); key = "${" + key + "}"; sql = this.genericDataService.replace(sql, key, pValue); } @@ -568,10 +558,4 @@ public ByteArrayOutputStream generatePentahoReportAsOutputStream(final String re */ return null; } - - private void validateReportName(final String name) { - if (!StringUtils.isBlank(name) && !name.matches(REPORT_NAME_REGEX_PATTERN)) { - throw new SQLInjectionException(); - } - } } From 676545b600858ce866e33e8a9353dd04ea082407 Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Sun, 11 Apr 2021 13:19:02 +0300 Subject: [PATCH 10/11] Code review changes (FINERACT-854) --- .../service/EmailReadPlatformServiceImpl.java | 14 ++++----- .../api/RunreportsApiResource.java | 10 +----- .../BasicAuthTenantDetailsServiceJdbc.java | 13 ++++---- .../service/JdbcTenantDetailsService.java | 31 +++++++------------ ...V365__reportCategoryList-FINERACT-1306.sql | 9 ++---- 5 files changed, 27 insertions(+), 50 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java index 126a404256d..71b83328409 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailReadPlatformServiceImpl.java @@ -130,9 +130,9 @@ public EmailData retrieveOne(final Long resourceId) { @Override public Collection retrieveAllPending(final SearchParameters searchParameters) { final String sqlPlusLimit = (searchParameters.getLimit() > 0) ? " limit 0, " + searchParameters.getLimit() : ""; - final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = " + sqlPlusLimit; + final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum =? " + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.PENDING.getValue() }); + return this.jdbcTemplate.query(sql, this.emailRowMapper, EmailMessageStatusType.PENDING.getValue()); } @Override @@ -140,15 +140,15 @@ public Collection retrieveAllSent(final SearchParameters searchParame final String sqlPlusLimit = (searchParameters.getLimit() > 0) ? " limit 0, " + searchParameters.getLimit() : ""; final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = ?" + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.SENT.getValue() }); + return this.jdbcTemplate.query(sql, this.emailRowMapper, EmailMessageStatusType.SENT.getValue()); } @Override public List retrieveExternalIdsOfAllSent(final Integer limit) { final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : ""; - final String sql = "select external_id from " + this.emailRowMapper.tableName() + " where status_enum = " + sqlPlusLimit; + final String sql = "select external_id from " + this.emailRowMapper.tableName() + " where status_enum =? " + sqlPlusLimit; - return this.jdbcTemplate.queryForList(sql, Long.class, new Object[] { EmailMessageStatusType.SENT.getValue() }); + return this.jdbcTemplate.queryForList(sql, Long.class, EmailMessageStatusType.SENT.getValue()); } @Override @@ -156,7 +156,7 @@ public Collection retrieveAllDelivered(final Integer limit) { final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : ""; final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = ?" + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.DELIVERED.getValue() }); + return this.jdbcTemplate.query(sql, this.emailRowMapper, EmailMessageStatusType.DELIVERED.getValue()); } @Override @@ -164,7 +164,7 @@ public Collection retrieveAllFailed(final SearchParameters searchPara final String sqlPlusLimit = (searchParameters.getLimit() > 0) ? " limit 0, " + searchParameters.getLimit() : ""; final String sql = "select " + this.emailRowMapper.schema() + " where emo.status_enum = ?" + sqlPlusLimit; - return this.jdbcTemplate.query(sql, this.emailRowMapper, new Object[] { EmailMessageStatusType.FAILED.getValue() }); + return this.jdbcTemplate.query(sql, this.emailRowMapper, EmailMessageStatusType.FAILED.getValue()); } @Override diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java index aa9bbb80f11..0f0c4c5b7c3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/RunreportsApiResource.java @@ -39,7 +39,6 @@ import javax.ws.rs.core.UriInfo; import org.apache.fineract.infrastructure.core.api.ApiParameterHelper; import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException; -import org.apache.fineract.infrastructure.dataqueries.service.DatatableReportingProcessService; import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService; import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider; import org.apache.fineract.infrastructure.report.service.ReportingProcessService; @@ -61,16 +60,13 @@ public class RunreportsApiResource { private final PlatformSecurityContext context; private final ReadReportingService readExtraDataAndReportingService; private final ReportingProcessServiceProvider reportingProcessServiceProvider; - private final DatatableReportingProcessService datatableReportingProcessService; @Autowired public RunreportsApiResource(final PlatformSecurityContext context, final ReadReportingService readExtraDataAndReportingService, - final ReportingProcessServiceProvider reportingProcessServiceProvider, - DatatableReportingProcessService aDatatableReportingProcessService) { + final ReportingProcessServiceProvider reportingProcessServiceProvider) { this.context = context; this.readExtraDataAndReportingService = readExtraDataAndReportingService; this.reportingProcessServiceProvider = reportingProcessServiceProvider; - datatableReportingProcessService = aDatatableReportingProcessService; } @GET @@ -109,10 +105,6 @@ public Response runReport(@PathParam("reportName") @Parameter(description = "rep // Pass through isSelfServiceUserReport so that ReportingProcessService implementations can use it queryParams.putSingle(IS_SELF_SERVICE_USER_REPORT_PARAMETER, Boolean.toString(isSelfServiceUserReport)); - if (parameterType) { - return datatableReportingProcessService.processRequest(reportName, queryParams); - } - String reportType = this.readExtraDataAndReportingService.getReportType(reportName, isSelfServiceUserReport); ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType); if (reportingProcessService == null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java index a5c1596cd75..bbbff0af544 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/BasicAuthTenantDetailsServiceJdbc.java @@ -49,7 +49,7 @@ public BasicAuthTenantDetailsServiceJdbc(@Qualifier("hikariTenantDataSource") fi private static final class TenantMapper implements RowMapper { private final boolean isReport; - private final StringBuilder sqlBuilder = new StringBuilder("SELECT t.id, ts.id as connectionId, ")// + private final StringBuilder sqlBuilder = new StringBuilder(" t.id, ts.id as connectionId , ")// .append(" t.timezone_id as timezoneId , t.name,t.identifier, ts.schema_name as schemaName, ts.schema_server as schemaServer,")// .append(" ts.schema_server_port as schemaServerPort, ts.schema_connection_parameters as schemaConnectionParameters, ts.auto_update as autoUpdate,")// .append(" ts.schema_username as schemaUsername, ts.schema_password as schemaPassword , ts.pool_initial_size as initialSize,")// @@ -60,7 +60,7 @@ private static final class TenantMapper implements RowMapper { - private final String tenantIdentifier; - - private final StringBuilder sqlBuilder = new StringBuilder("SELECT t.id, ts.id as connectionId, ")// + private final StringBuilder sqlBuilder = new StringBuilder("t.id, ts.id as connectionId , ")// .append(" t.timezone_id as timezoneId , t.name,t.identifier, ts.schema_name as schemaName, ts.schema_server as schemaServer,")// .append(" ts.schema_server_port as schemaServerPort, ts.schema_connection_parameters as schemaConnectionParameters, ts.auto_update as autoUpdate,")// .append(" ts.schema_username as schemaUsername, ts.schema_password as schemaPassword , ts.pool_initial_size as initialSize,")// @@ -62,28 +60,21 @@ private static final class TenantMapper implements RowMapper findAllTenants() { - final TenantMapper rm = new TenantMapper(null); - final String sql = rm.schema(); + final TenantMapper rm = new TenantMapper(); + final String sql = "select " + rm.schema(); final List fineractPlatformTenants = this.jdbcTemplate.query(sql, rm, new Object[] {}); return fineractPlatformTenants; diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql index 794ab210e6f..70ffd5df96e 100644 --- a/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V365__reportCategoryList-FINERACT-1306.sql @@ -18,10 +18,5 @@ -- -- two tables added: ReportCategoryList and FullReportList (FINERACT-1306) -INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report) -SELECT 'ReportCategoryList', 'Table', NULL, NULL, NULL, 1, 1 -ON DUPLICATE key UPDATE report_name = 'ReportCategoryList'; - -INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report) -SELECT 'FullReportList', 'Table', NULL, NULL, NULL, 1, 1 -ON DUPLICATE key UPDATE report_name = 'FullReportList'; +INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report)VALUES ("ReportCategoryList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1); +INSERT INTO stretchy_report (report_name, report_type, report_category, report_sql, description, core_report, use_report)VALUES ("FullReportList", 'Table', '(NULL)', '(NULL)', '(NULL)', 1, 1); From 0a36b42ef7101cedf4eeed9b062be097affb1003 Mon Sep 17 00:00:00 2001 From: Joseph Makara Date: Mon, 12 Apr 2021 19:59:40 +0300 Subject: [PATCH 11/11] Use prepared statements instead of string concatenated SQL everywhere (FINERACT-854) --- .../service/ProvisioningEntriesReadPlatformServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java index 5396bfc9b5e..bb8994d3fb9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/provisioning/service/ProvisioningEntriesReadPlatformServiceImpl.java @@ -75,8 +75,8 @@ private LoanProductProvisioningEntryMapper() { .append(" LEFT JOIN m_loan loan on sch.loan_id = loan.id") .append(" JOIN m_loanproduct_provisioning_mapping lpm on lpm.product_id = loan.product_id") .append(" JOIN m_provisioning_criteria_definition pcd on pcd.criteria_id = lpm.criteria_id and ") - .append("(pcd.min_age <= GREATEST(datediff(?").append(",sch.duedate),0) and ").append("GREATEST(datediff(?") - .append(",sch.duedate),0) <= pcd.max_age) and ").append("pcd.criteria_id is not null ") + .append("(pcd.min_age <= GREATEST(datediff(?,sch.duedate),0) and GREATEST(datediff(?") + .append(",sch.duedate),0) <= pcd.max_age) and pcd.criteria_id is not null ") .append("LEFT JOIN m_client mclient ON mclient.id = loan.client_id ") .append("LEFT JOIN m_group mgroup ON mgroup.id = loan.group_id ") .append("where loan.loan_status_id=300 and sch.duedate = ")