diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java index 6e9d1e8a2..31eaade3d 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/DataTableApiResource.java @@ -1,20 +1,22 @@ package org.mifosng.platform.api; -import java.util.ArrayList; -import java.util.List; - import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; -import org.mifosng.platform.InvalidSqlException; -import org.mifosng.platform.api.data.ApiParameterError; -import org.mifosng.platform.exceptions.PlatformApiDataValidationException; +import org.mifosng.platform.api.data.GenericResultsetData; +import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; +import org.mifosng.platform.api.infrastructure.ApiParameterHelper; +import org.mifosng.platform.exceptions.NoAuthorizationException; import org.mifosng.platform.noncore.ReadWriteNonCoreDataService; +import org.mifosng.platform.security.PlatformSecurityContext; +import org.mifosng.platform.user.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -27,33 +29,58 @@ public class DataTableApiResource { // private final static Logger logger = // LoggerFactory.getLogger(DataTableApiResource.class); + private final PlatformSecurityContext context; + + @Autowired + public DataTableApiResource(final PlatformSecurityContext context) { + this.context = context; + } + @Autowired private ReadWriteNonCoreDataService readWriteNonCoreDataService; + @Autowired + private ApiJsonSerializerService apiJsonSerializerService; + @GET @Path("{datatable}/{id}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String extraData(@PathParam("datatable") final String datatable, + public String getDatatable(@PathParam("datatable") final String datatable, @PathParam("id") final Long id, @QueryParam("sqlFields") final String sqlFields, @QueryParam("sqlSearch") final String sqlSearch, - @QueryParam("sqlOrder") final String sqlOrder) { + @QueryParam("sqlOrder") final String sqlOrder, + @Context final UriInfo uriInfo) { + + checkUserPermissionForDatatable(datatable, "READ"); - return this.readWriteNonCoreDataService.retrieveDataTable(datatable, id, - sqlFields, sqlSearch, sqlOrder); /* - * try { return this.readWriteNonCoreDataService.retrieveDataTable( - * datatable, sqlFields, sqlSearch, sqlOrder); } catch - * (InvalidSqlException e) { List - * dataValidationErrors = new ArrayList(); - * ApiParameterError error = ApiParameterError.parameterError( - * "extradata.invalid.sql", "The sql is invalid.", "sql", e.getSql()); - * dataValidationErrors.add(error); throw new - * PlatformApiDataValidationException( - * "validation.msg.validation.errors.exist", "Validation errors exist.", - * dataValidationErrors); } + * Dont use this for now... but its the code for returning data as json + * objects rather than a generic resultset String resultStr = + * this.readWriteNonCoreDataService + * .retrieveDataTableJSONObject(datatable, id, sqlFields, sqlSearch, + * sqlOrder); */ + + GenericResultsetData results = this.readWriteNonCoreDataService + .retrieveDataTableGenericResultSet(datatable, id, sqlFields, + sqlSearch, sqlOrder); + + boolean prettyPrints = ApiParameterHelper.prettyPrint(uriInfo + .getQueryParameters()); + return this.apiJsonSerializerService + .serializeGenericResultsetDataToJson(prettyPrints, results); + } -} \ No newline at end of file + private void checkUserPermissionForDatatable(String datatable, + String accessType) { + AppUser currentUser = context.authenticatedUser(); + if (currentUser.hasNotPermissionForDatatable(datatable, accessType)) { + throw new NoAuthorizationException("Not Authorised to " + + accessType + " Data Table: " + datatable); + } + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnHeader.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnHeader.java index 42ce267cd..94445e1dd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnHeader.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnHeader.java @@ -10,6 +10,7 @@ public class ResultsetColumnHeader { private Integer columnLength; private String columnDisplayType; private List columnValues = new ArrayList(); + private List columnValuesNew = new ArrayList(); public ResultsetColumnHeader() { @@ -55,4 +56,12 @@ public class ResultsetColumnHeader { this.columnDisplayType = columnDisplayType; } + public List getColumnValuesNew() { + return columnValuesNew; + } + + public void setColumnValuesNew(List columnValuesNew) { + this.columnValuesNew = columnValuesNew; + } + } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnValue.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnValue.java new file mode 100644 index 000000000..a3f89eea7 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ResultsetColumnValue.java @@ -0,0 +1,28 @@ +package org.mifosng.platform.api.data; + +public class ResultsetColumnValue { + + private Long id; + private String Value; + + public ResultsetColumnValue() { + + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getValue() { + return Value; + } + + public void setValue(String value) { + Value = value; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java index ccd1fdf7f..a64356f33 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java @@ -16,4 +16,6 @@ public interface GenericDataService { String wrapSQL(String sql); + String getDatabaseName(); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java index 8e75949bd..b6f860eae 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java @@ -173,4 +173,14 @@ public class GenericDataServiceImpl implements GenericDataService { e.getMessage(), "Error closing database connection"); } } + + @Override + public String getDatabaseName() { + try { + return dataSource.getConnection().getCatalog(); + } catch (SQLException e) { + throw new PlatformDataIntegrityException("error.msg.sql.error", + e.getMessage(), "Error Accessing Database Name"); + } + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java index 04c20c5dc..b7aa61015 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataService.java @@ -13,8 +13,12 @@ public interface ReadWriteNonCoreDataService { GenericResultsetData retrieveExtraData(String type, String set, Long id); void updateExtraData(String type, String set, Long id, - Map queryParams); + Map queryParams); - String retrieveDataTable(String datatable, Long id, String sqlFields, String sqlSearch, String sqlOrder); + GenericResultsetData retrieveDataTableGenericResultSet(String datatable, + Long id, String sqlFields, String sqlSearch, String sqlOrder); + + String retrieveDataTableJSONObject(String datatable, Long id, + String sqlFields, String sqlSearch, String sqlOrder); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java index 446229e9a..4dacd7aee 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java @@ -94,8 +94,8 @@ public class ReadWriteNonCoreDataServiceImpl implements @Override public GenericResultsetData retrieveExtraData(String type, String set, - Long id) { - + Long id) { + long startTime = System.currentTimeMillis(); checkMainResourceExistsWithinScope(type, id); @@ -475,16 +475,34 @@ public class ReadWriteNonCoreDataServiceImpl implements } @Override - public String retrieveDataTable(String datatable, Long id, String sqlFields, - String sqlSearch, String sqlOrder) { + public String retrieveDataTableJSONObject(String datatable, Long id, + String sqlFields, String sqlSearch, String sqlOrder) { + long startTime = System.currentTimeMillis(); + + GenericResultsetData result = retrieveDataTableGenericResultSet( + datatable, id, sqlFields, sqlSearch, sqlOrder); + + String jsonString = generateJsonFromGenericResultsetData(result); + + long elapsed = System.currentTimeMillis() - startTime; + logger.info("FINISHING DATATABLE JSON OBJECT: " + datatable + " Elapsed Time: " + + elapsed); + return jsonString; + } + + @Override + public GenericResultsetData retrieveDataTableGenericResultSet( + String datatable, Long id, String sqlFields, String sqlSearch, + String sqlOrder) { + long startTime = System.currentTimeMillis(); String applicationTableName = getApplicationTableName(datatable); checkMainResourceExistsWithinScope(applicationTableName, id); - + String fkField = applicationTableName.substring(2) + "_id"; - + String sql = "select "; if (sqlFields != null) sql = sql + sqlFields; @@ -501,24 +519,23 @@ public class ReadWriteNonCoreDataServiceImpl implements GenericResultsetData result = genericDataService .fillGenericResultSet(sql); - String jsonString = generateJsonFromGenericResultsetData(result); - - logger.info("JSON is: " + jsonString); long elapsed = System.currentTimeMillis() - startTime; logger.info("FINISHING DATATABLE: " + datatable + " Elapsed Time: " + elapsed); - return jsonString; + + return result; } - + private String getApplicationTableName(String datatable) { - String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = '" + datatable + "'"; + String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = '" + + datatable + "'"; CachedRowSet rs = genericDataService.getCachedResultSet(sql, "SQL : " + sql); if (rs.size() == 0) throw new DataTableNotFoundException(datatable); - + try { rs.next(); return rs.getString("application_table_name"); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java b/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java index cae3a9bd8..f5fabea16 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java @@ -262,7 +262,28 @@ public class AppUser extends AbstractAuditableCustom implements public boolean hasNotPermissionForReport(String reportName) { - if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "CAN_RUN_" + reportName)) + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", + "CAN_RUN_" + reportName)) + return true; + + return false; + } + + public boolean hasNotPermissionForDatatable(String datatable, + String accessType) { + + String matchPermission = "CAN_" + accessType + "_" + datatable; + + if (accessType.equalsIgnoreCase("READ")) { + + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", + matchPermission)) + return true; + + return false; + } + + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", matchPermission)) return true; return false; @@ -275,15 +296,16 @@ public class AppUser extends AbstractAuditableCustom implements if (accessType.equalsIgnoreCase("READ")) { - if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", matchPermission)) + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", + matchPermission)) return true; - + return false; } if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", matchPermission)) return true; - + return false; }