Adhoc Query

This commit is contained in:
Kasem
2017-07-29 18:05:46 +06:00
parent afdc665b52
commit 2e259b1583
21 changed files with 1468 additions and 3 deletions
@@ -0,0 +1,170 @@
/**
* 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.adhocquery.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.adhocquery.data.AdHocData;
import org.apache.fineract.adhocquery.service.AdHocReadPlatformService;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/adhocquery")
@Component
@Scope("singleton")
public class AdHocApiResource {
/**
* The set of parameters that are supported in response for {@link AdhocData}
*/
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "name", "query", "tableName","tableField","isActive","createdBy","createdOn","createdById","updatedById","updatedOn","email"));
private final PlatformSecurityContext context;
private final AdHocReadPlatformService adHocReadPlatformService;
private final DefaultToApiJsonSerializer<AdHocData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public AdHocApiResource(final PlatformSecurityContext context, final AdHocReadPlatformService readPlatformService,
final DefaultToApiJsonSerializer<AdHocData> toApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.adHocReadPlatformService = readPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo) {
this.context.authenticatedUser();
final Collection<AdHocData> adhocs = this.adHocReadPlatformService.retrieveAllAdHocQuery();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, adhocs, this.RESPONSE_DATA_PARAMETERS);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Path("template")
public String template(@Context final UriInfo uriInfo) {
this.context.authenticatedUser();
final AdHocData user = this.adHocReadPlatformService.retrieveNewAdHocDetails();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, user, this.RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createAdHocQuery(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createAdHoc() //
.withJson(apiRequestBodyAsJson) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@GET
@Path("{adHocId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAdHocQuery(@PathParam("adHocId") final Long adHocId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
final AdHocData adhoc = this.adHocReadPlatformService.retrieveOne(adHocId);
return this.toApiJsonSerializer.serialize(settings, adhoc, this.RESPONSE_DATA_PARAMETERS);
}
@PUT
@Path("{adHocId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String update(@PathParam("adHocId") final Long adHocId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateAdHoc(adHocId) //
.withJson(apiRequestBodyAsJson) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
/**
* Delete AdHocQuery
*
* @param adHocId
* @return
*/
@DELETE
@Path("{adHocId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteAdHocQuery(@PathParam("adHocId") final Long adHocId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteAdHoc(adHocId) //
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
}
@@ -0,0 +1,55 @@
/**
* 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.adhocquery.api;
import java.util.HashSet;
import java.util.Set;
/***
* Enum of all parameters passed in while creating/updating a AdHocQuery
***/
public enum AdHocJsonInputParams {
ID("id"), NAME("name"),QUERY("query"),TABLENAME("tableName"),TABLEFIELD("tableFields"), ISACTIVE("isActive"),EMAIL("email");
private final String value;
private AdHocJsonInputParams(final String value) {
this.value = value;
}
private static final Set<String> values = new HashSet<>();
static {
for (final AdHocJsonInputParams type : AdHocJsonInputParams.values()) {
values.add(type.value);
}
}
public static Set<String> getAllValues() {
return values;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public String getValue() {
return this.value;
}
}
@@ -0,0 +1,122 @@
/**
* 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.adhocquery.data;
import java.util.Collection;
import org.apache.fineract.organisation.office.data.OfficeData;
import org.apache.fineract.useradministration.data.AppUserData;
import org.apache.fineract.useradministration.data.RoleData;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
/**
* Immutable data object represent note or case information AdHocData
*
*/
public class AdHocData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final String name;
@SuppressWarnings("unused")
private final String query;
@SuppressWarnings("unused")
private final String tableName;
@SuppressWarnings("unused")
private final String tableFields;
@SuppressWarnings("unused")
private final String email;
@SuppressWarnings("unused")
private final boolean isActive;
@SuppressWarnings("unused")
private final DateTime createdOn;
@SuppressWarnings("unused")
private final Long createdById;
@SuppressWarnings("unused")
private final Long updatedById;
@SuppressWarnings("unused")
private final DateTime updatedOn;
@SuppressWarnings("unused")
private final String createdBy;
public AdHocData(final Long id, final String name,final String query, final String tableName,final String tableFields,
final boolean isActive, final DateTime createdOn, final Long createdById,final Long updatedById,
final DateTime updatedOn,final String createdBy,final String email
) {
this.id = id;
this.name=name;
this.query=query;
this.tableName = tableName;
this.tableFields = tableFields;
this.isActive = isActive;
this.createdOn = createdOn;
this.createdById = createdById;
this.updatedById=updatedById;
this.updatedOn=updatedOn;
this.createdBy=createdBy;
this.email=email;
}
public static AdHocData template() {
AdHocData adHocData = new AdHocData(null,null,null,null,null,false,null,null,null,null,null,null);
return adHocData;
}
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getQuery() {
return this.query;
}
public String getTableName() {
return this.tableName;
}
public String getTableFields() {
return this.tableFields;
}
public String getEmail() {
return this.email;
}
public boolean isActive() {
return this.isActive;
}
public DateTime getCreatedOn() {
return this.createdOn;
}
public Long getCreatedById() {
return this.createdById;
}
public Long getUpdatedById() {
return this.updatedById;
}
public DateTime getUpdatedOn() {
return this.updatedOn;
}
public String getCreatedBy() {
return this.createdBy;
}
}
@@ -0,0 +1,153 @@
/**
* 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.adhocquery.domain;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.adhocquery.api.AdHocJsonInputParams;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
import org.apache.fineract.useradministration.domain.AppUser;
@Entity
@Table(name = "m_adhoc")
public class AdHoc extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "name", length = 100)
private String name;
@Column(name = "query", length = 2000)
private String query;
@Column(name = "table_name", length = 100)
private String tableName;
@Column(name = "table_fields", length = 2000)
private String tableFields;
@Column(name = "email", length = 500)
private String email;
@Column(name = "IsActive", nullable = false)
private boolean isActive = false;
private AdHoc(final String name, final String query,final String tableName,final String tableFields ,final String email,final boolean isActive) {
this.name = StringUtils.defaultIfEmpty(name, null);
this.query=StringUtils.defaultIfEmpty(query,null);
this.tableName=StringUtils.defaultIfEmpty(tableName,null);
this.tableFields=StringUtils.defaultIfEmpty(tableFields,null);
this.email=StringUtils.defaultIfEmpty(email,null);
this.isActive = BooleanUtils.toBooleanDefaultIfNull(isActive, false);
}
public static AdHoc fromJson(final JsonCommand command) {
final String name = command.stringValueOfParameterNamed(AdHocJsonInputParams.NAME.getValue());
String commandQuery=command.stringValueOfParameterNamed(AdHocJsonInputParams.QUERY.getValue());
SQLInjectionValidator.validateAdhocQuery(commandQuery);
final String query = commandQuery;
final String tableName = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLENAME.getValue());
final String tableFields = command.stringValueOfParameterNamed(AdHocJsonInputParams.TABLEFIELD.getValue());
final String email = command.stringValueOfParameterNamed(AdHocJsonInputParams.EMAIL.getValue());
final boolean isActive = command.booleanPrimitiveValueOfParameterNamed(AdHocJsonInputParams.ISACTIVE.getValue());
return new AdHoc(name,query,tableName,tableFields ,email,isActive);
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String nameParamName = "name";
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
final String newValue = command.stringValueOfParameterNamed(nameParamName);
actualChanges.put(nameParamName, newValue);
this.name = newValue;
}
final String descriptionParamName = "query";
if (command.isChangeInStringParameterNamed(descriptionParamName, this.query)) {
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
actualChanges.put(descriptionParamName, newValue);
this.query = newValue;
}
final String tableName = "tableName";
if (command.isChangeInStringParameterNamed(tableName, this.tableName)) {
final String newValue = command.stringValueOfParameterNamed(tableName);
actualChanges.put(tableName, newValue);
this.tableName = newValue;
}
final String tableField = "tableField";
if (command.isChangeInStringParameterNamed(tableField, this.tableFields)) {
final String newValue = command.stringValueOfParameterNamed(tableField);
actualChanges.put(tableField, newValue);
this.tableFields = newValue;
}
final String email = "email";
if (command.isChangeInStringParameterNamed(email, this.email)) {
final String newValue = command.stringValueOfParameterNamed(email);
actualChanges.put(email, newValue);
this.email = newValue;
}
final String paramisActive = "isActive";
if (command.isChangeInBooleanParameterNamed(paramisActive, this.isActive)) {
final Boolean newValue = command.booleanObjectValueOfParameterNamed(paramisActive);
actualChanges.put(paramisActive, newValue);
this.isActive = newValue;
}
return actualChanges;
}
public String getName() {
return name;
}
public String getQuery() {
return query;
}
public String getTableName() {
return tableName;
}
public String getTableFields() {
return tableFields;
}
public boolean isActive() {
return this.isActive;
}
public String getEmail() {
return email;
}
public void disableActive() {
this.isActive = true;
}
public void enableActive() {
this.isActive = false;
}
}
@@ -0,0 +1,26 @@
/**
* 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.adhocquery.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface AdHocRepository extends JpaRepository<AdHoc, Long>, JpaSpecificationExecutor<AdHoc> {
// no added behaviour
}
@@ -0,0 +1,32 @@
/**
* 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.adhocquery.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when AdHoc resources are not
* found.
*/
public class AdHocNotFoundException extends AbstractPlatformResourceNotFoundException {
public AdHocNotFoundException(final Long id) {
super("error.msg.adhocquery.adhoc.id.invalid", "Adhoc Record with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,47 @@
/**
* 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.adhocquery.handler;
import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "ADHOC", action = "CREATE")
public class CreateAdHocCommandHandler implements NewCommandSourceHandler {
private final AdHocWritePlatformService writePlatformService;
@Autowired
public CreateAdHocCommandHandler(final AdHocWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.createAdHocQuery(command);
}
}
@@ -0,0 +1,47 @@
/**
* 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.adhocquery.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "ADHOC", action = "DELETE")
public class DeleteAdHocCommandHandler implements NewCommandSourceHandler {
private final AdHocWritePlatformService writePlatformService;
@Autowired
public DeleteAdHocCommandHandler(final AdHocWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.deleteAdHocQuery(command.entityId());
}
}
@@ -0,0 +1,48 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.adhocquery.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.adhocquery.service.AdHocWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "ADHOC", action = "UPDATE")
public class UpdateAdHocCommandHandler implements NewCommandSourceHandler {
private final AdHocWritePlatformService writePlatformService;
@Autowired
public UpdateAdHocCommandHandler(final AdHocWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
final Long adHocId = command.entityId();
return this.writePlatformService.updateAdHocQuery(adHocId, command);
}
}
@@ -0,0 +1,127 @@
/**
* 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.adhocquery.service;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public final class AdHocDataValidator {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("name","query","tableName","tableFields","email","isActive"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public AdHocDataValidator(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForCreate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("adhoc");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
final String description = this.fromApiJsonHelper.extractStringNamed("query", element);
baseDataValidator.reset().parameter("query").value(description).notBlank().notExceedingLengthOf(2000);
final String tableName = this.fromApiJsonHelper.extractStringNamed("tableName", element);
baseDataValidator.reset().parameter("tableName").value(tableName).notBlank().notExceedingLengthOf(100);
final String tableFields = this.fromApiJsonHelper.extractStringNamed("tableFields", element);
baseDataValidator.reset().parameter("tableFields").value(tableFields).notBlank().notExceedingLengthOf(1000);
final String email = this.fromApiJsonHelper.extractStringNamed("email", element);
baseDataValidator.reset().parameter("email").value(email).notBlank().notExceedingLengthOf(500);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("adhoc");
final JsonElement element = this.fromApiJsonHelper.parse(json);
if (this.fromApiJsonHelper.parameterExists("name", element)) {
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
}
if (this.fromApiJsonHelper.parameterExists("query", element)) {
final String query = this.fromApiJsonHelper.extractStringNamed("query", element);
baseDataValidator.reset().parameter("query").value(query).notBlank().notExceedingLengthOf(2000);
}
if (this.fromApiJsonHelper.parameterExists("tableName", element)) {
final String tableName = this.fromApiJsonHelper.extractStringNamed("tableName", element);
baseDataValidator.reset().parameter("tableName").value(tableName).notBlank().notExceedingLengthOf(100);
}
if (this.fromApiJsonHelper.parameterExists("tableFields", element)) {
final String tableField = this.fromApiJsonHelper.extractStringNamed("tableFields", element);
baseDataValidator.reset().parameter("tableFields").value(tableField).notBlank().notExceedingLengthOf(2000);
}
if (this.fromApiJsonHelper.parameterExists("email", element)) {
final String email = this.fromApiJsonHelper.extractStringNamed("email", element);
baseDataValidator.reset().parameter("email").value(email).notBlank().notExceedingLengthOf(500);
}
/*if (this.fromApiJsonHelper.parameterExists("isActive", element)) {
final Integer isActive = this.fromApiJsonHelper.extractIntegerNamed("isActive", element, Locale.getDefault());
baseDataValidator.reset().parameter("isActive").value(isActive).notNull().inMinMaxRange(1, 2);
}*/
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -0,0 +1,34 @@
/**
* 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.adhocquery.service;
import java.util.Collection;
import org.apache.fineract.adhocquery.data.AdHocData;
public interface AdHocReadPlatformService {
Collection<AdHocData> retrieveAllAdHocQuery();
Collection<AdHocData> retrieveAllActiveAdHocQuery();
AdHocData retrieveOne(Long adHocId);
AdHocData retrieveNewAdHocDetails();
}
@@ -0,0 +1,109 @@
/**
* 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.adhocquery.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.apache.fineract.adhocquery.data.AdHocData;
import org.apache.fineract.adhocquery.exception.AdHocNotFoundException;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class AdHocReadPlatformServiceImpl implements AdHocReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final AdHocMapper adHocRowMapper;
@Autowired
public AdHocReadPlatformServiceImpl(final RoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.adHocRowMapper = new AdHocMapper();
}
@Override
public Collection<AdHocData> retrieveAllAdHocQuery() {
final String sql = "select " + this.adHocRowMapper.schema() + " order by r.id";
return this.jdbcTemplate.query(sql, this.adHocRowMapper);
}
@Override
public Collection<AdHocData> retrieveAllActiveAdHocQuery() {
final String sql = "select " + this.adHocRowMapper.schema() + " where r.IsActive = 1 order by r.id";
return this.jdbcTemplate.query(sql, this.adHocRowMapper);
}
@Override
public AdHocData retrieveOne(final Long id) {
try {
final String sql = "select " + this.adHocRowMapper.schema() + " where r.id=?";
return this.jdbcTemplate.queryForObject(sql, this.adHocRowMapper, new Object[] { id });
} catch (final EmptyResultDataAccessException e) {
throw new AdHocNotFoundException(id);
}
}
protected static final class AdHocMapper implements RowMapper<AdHocData> {
@Override
public AdHocData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final String name = rs.getString("name");
final String query = rs.getString("query");
final String tableName=rs.getString("tableName");
final String tableFields=rs.getString("tableField");
final Boolean isActive = rs.getBoolean("isActive");
final DateTime createdDate = JdbcSupport.getDateTime(rs, "createdDate");
final Long createdById = JdbcSupport.getLong(rs, "createdById");
final Long updatedById=JdbcSupport.getLong(rs, "updatedById");
final DateTime updatedOn=JdbcSupport.getDateTime(rs, "updatedOn");
final String createdByUsername=rs.getString("createdBy");
final String email=rs.getString("email");
return new AdHocData(id,name,query, tableName,tableFields,isActive,createdDate,createdById,updatedById,updatedOn,createdByUsername,email);
}
public String schema() {
return " r.id as id, r.name as name, r.query as query, r.table_name as tableName,r.table_fields as tableField ,r.IsActive as isActive ,r.email as email ,"
+" r.created_date as createdDate, r.createdby_id as createdById,cb.username as createdBy,r.lastmodifiedby_id as updatedById ,r.lastmodified_date as updatedOn "
+ " from m_adhoc r left join m_appuser cb on cb.id=r.createdby_id left join m_appuser mb on mb.id=r.lastmodifiedby_id";
}
}
@Override
public AdHocData retrieveNewAdHocDetails() {
return AdHocData.template();
}
}
@@ -0,0 +1,23 @@
/**
* 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.adhocquery.service;
public interface AdHocScheduledJobRunnerService {
void generateClientSchedule();
}
@@ -0,0 +1,77 @@
/**
* 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.adhocquery.service;
import java.util.Collection;
import org.apache.fineract.adhocquery.data.AdHocData;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service(value = "adHocScheduledJobRunnerService")
public class AdHocScheduledJobRunnerServiceImpl implements AdHocScheduledJobRunnerService {
private final static Logger logger = LoggerFactory.getLogger(AdHocScheduledJobRunnerServiceImpl.class);
private final AdHocReadPlatformService adHocReadPlatformService;
private final JdbcTemplate jdbcTemplate;
@Autowired
public AdHocScheduledJobRunnerServiceImpl(final RoutingDataSource dataSource,
final AdHocReadPlatformService adHocReadPlatformService
) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.adHocReadPlatformService = adHocReadPlatformService;
}
@Transactional
@Override
@CronTarget(jobName = JobName.GENERATE_ADHOCCLIENT_SCEHDULE)
public void generateClientSchedule() {
final Collection<AdHocData> adhocs = this.adHocReadPlatformService.retrieveAllActiveAdHocQuery();
if(adhocs.size()>0){
adhocs.forEach(adhoc->{
//jdbcTemplate.execute("truncate table "+adhoc.getTableName());
final StringBuilder insertSqlBuilder = new StringBuilder(900);
insertSqlBuilder
.append("INSERT INTO ")
.append(adhoc.getTableName()+"(")
.append(adhoc.getTableFields()+") ")
.append(adhoc.getQuery());
if (insertSqlBuilder.length() > 0) {
final int result = this.jdbcTemplate.update(insertSqlBuilder.toString());
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by inserted: " + result);
}
});
}else{
logger.info(ThreadLocalContextUtil.getTenant().getName() + "Nothing to update ");
}
}
}
@@ -0,0 +1,35 @@
/**
* 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.adhocquery.service;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
public interface AdHocWritePlatformService {
CommandProcessingResult createAdHocQuery(JsonCommand command);
CommandProcessingResult updateAdHocQuery(Long adHocId, JsonCommand command);
CommandProcessingResult deleteAdHocQuery(Long adHocId);
CommandProcessingResult disableAdHocQuery(Long adHocId);
CommandProcessingResult enableAdHocQuery(Long adHocId);
}
@@ -0,0 +1,193 @@
/**
* 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.adhocquery.service;
import java.util.Map;
import org.apache.fineract.adhocquery.domain.AdHoc;
import org.apache.fineract.adhocquery.domain.AdHocRepository;
import org.apache.fineract.adhocquery.exception.AdHocNotFoundException;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AdHocWritePlatformServiceJpaRepositoryImpl implements AdHocWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(AdHocWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final AdHocRepository adHocRepository;
private final AdHocDataValidator adHocCommandFromApiJsonDeserializer;
@Autowired
public AdHocWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final AdHocRepository adHocRepository,
final AdHocDataValidator adHocCommandFromApiJsonDeserializer) {
this.context = context;
this.adHocRepository = adHocRepository;
this.adHocCommandFromApiJsonDeserializer = adHocCommandFromApiJsonDeserializer;
}
@Transactional
@Override
public CommandProcessingResult createAdHocQuery(final JsonCommand command) {
try {
this.context.authenticatedUser();
this.adHocCommandFromApiJsonDeserializer.validateForCreate(command.json());
final AdHoc entity = AdHoc.fromJson(command);
this.adHocRepository.save(entity);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(entity.getId()).build();
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.build();
}
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue
* is.
*/
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("unq_name")) {
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.adhocquery.duplicate.name", "AdHocQuery with name `" + name + "` already exists",
"name", name);
}
logAsErrorUnexpectedDataIntegrityException(dve);
throw new PlatformDataIntegrityException("error.msg.adhocquery.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
logger.error(dve.getMessage(), dve);
}
@Transactional
@Override
public CommandProcessingResult updateAdHocQuery(final Long adHocId, final JsonCommand command) {
try {
this.context.authenticatedUser();
this.adHocCommandFromApiJsonDeserializer.validateForUpdate(command.json());
final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
final Map<String, Object> changes = adHoc.update(command);
if (!changes.isEmpty()) {
this.adHocRepository.saveAndFlush(adHoc);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(adHocId) //
.with(changes) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.build();
}
}
/**
* Method for Delete adhoc
*/
@Transactional
@Override
public CommandProcessingResult deleteAdHocQuery(Long adHocId) {
try {
/**
* Checking the adhocQuery present in DB or not using adHocId
*/
final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
this.adHocRepository.delete(adHoc);
return new CommandProcessingResultBuilder().withEntityId(adHocId).build();
} catch (final DataIntegrityViolationException e) {
throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + e.getMostSpecificCause());
}
}
/**
* Method for disabling the adhocquery
*/
@Transactional
@Override
public CommandProcessingResult disableAdHocQuery(Long adHocId) {
try {
/**
* Checking the adhocquery present in DB or not using adHocId
*/
final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
adHoc.disableActive();
this.adHocRepository.save(adHoc);
return new CommandProcessingResultBuilder().withEntityId(adHocId).build();
} catch (final DataIntegrityViolationException e) {
throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + e.getMostSpecificCause());
}
}
/**
* Method for Enabling the Active
*/
@Transactional
@Override
public CommandProcessingResult enableAdHocQuery(Long adHocId) {
try {
/**
* Checking the adHoc present in DB or not using id
*/
final AdHoc adHoc = this.adHocRepository.findOne(adHocId);
if (adHoc == null) { throw new AdHocNotFoundException(adHocId); }
adHoc.enableActive();
this.adHocRepository.save(adHoc);
return new CommandProcessingResultBuilder().withEntityId(adHocId).build();
} catch (final DataIntegrityViolationException e) {
throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + e.getMostSpecificCause());
}
}
}
@@ -2977,4 +2977,43 @@ public class CommandWrapperBuilder {
this.href = "/savingsaccounts/" + accountId + "?command=unblock";
return this;
}
public CommandWrapperBuilder disableAdHoc(Long adHocId) {
this.actionName = "DISABLE";
this.entityName = "ADHOC";
this.entityId = adHocId;
this.href = "/adhoc/" + adHocId + "/disbale";
this.json = "{}";
return this;
}
public CommandWrapperBuilder enableAdHoc(Long adHocId) {
this.actionName = "ENABLE";
this.entityName = "ADHOC";
this.entityId = adHocId;
this.href = "/adhoc/" + adHocId + "/enable";
this.json = "{}";
return this;
}
public CommandWrapperBuilder createAdHoc() {
this.actionName = "CREATE";
this.entityName = "ADHOC";
this.href = "/adhocquery/template";
return this;
}
public CommandWrapperBuilder updateAdHoc(final Long adHocId) {
this.actionName = "UPDATE";
this.entityName = "ADHOC";
this.entityId = adHocId;
this.href = "/adhocquery/" + adHocId;
return this;
}
public CommandWrapperBuilder deleteAdHoc(Long adHocId) {
this.actionName = "DELETE";
this.entityName = "ADHOC";
this.entityId = adHocId;
this.href = "/adhocquery/" + adHocId;
this.json = "{}";
return this;
}
}
@@ -45,8 +45,8 @@ public enum JobName {
EXECUTE_REPORT_MAILING_JOBS("Execute Report Mailing Jobs"),
UPDATE_SMS_OUTBOUND_WITH_CAMPAIGN_MESSAGE("Update SMS Outbound with Campaign Message"),
SEND_MESSAGES_TO_SMS_GATEWAY("Send Messages to SMS Gateway"),
GET_DELIVERY_REPORTS_FROM_SMS_GATEWAY("Get Delivery Reports from SMS Gateway");
GET_DELIVERY_REPORTS_FROM_SMS_GATEWAY("Get Delivery Reports from SMS Gateway"),
GENERATE_ADHOCCLIENT_SCEHDULE("Generate AdhocClient Schedule");
private final String name;
private JobName(final String name) {
@@ -46,6 +46,83 @@ public class SQLInjectionValidator {
}
}
for (String comments : COMMENTS) {
if (lowerCaseSQL.contains(comments)) {
throw new SQLInjectionException();
}
}
//Removing the space before and after '=' operator
//String s = " \" OR 1 = 1"; For the cases like this
boolean injectionFound = false;
String inputSqlString = lowerCaseSQL;
while (inputSqlString.indexOf(" =") > 0) { //Don't remove space before = operator
inputSqlString = inputSqlString.replaceAll(" =", "=");
}
while (inputSqlString.indexOf("= ") > 0) { //Don't remove space after = operator
inputSqlString = inputSqlString.replaceAll("= ", "=");
}
StringTokenizer tokenizer = new StringTokenizer(inputSqlString, " ");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken().trim();
if (token.equals("'")) {
if (tokenizer.hasMoreElements()) {
String nextToken = tokenizer.nextToken().trim();
if (!nextToken.equals("'")) {
injectionFound = true;
break;
}
} else {
injectionFound = true;
break ;
}
}
if (token.equals("\"")) {
if (tokenizer.hasMoreElements()) {
String nextToken = tokenizer.nextToken().trim();
if (!nextToken.equals("\"")) {
injectionFound = true;
break;
}
} else {
injectionFound = true;
break ;
}
} else if (token.indexOf('=') > 0) {
StringTokenizer operatorToken = new StringTokenizer(token, "=");
String operand = operatorToken.nextToken().trim();
if (!operatorToken.hasMoreTokens()) {
injectionFound = true;
break;
}
String value = operatorToken.nextToken().trim();
if (operand.equals(value)) {
injectionFound = true;
break;
}
}
}
if (injectionFound) {
throw new SQLInjectionException();
}
Pattern pattern = Pattern.compile(SQL_PATTERN);
Matcher matcher = pattern.matcher(sqlSearch);
if (!matcher.matches()) {
throw new SQLInjectionException();
}
}
public final static void validateAdhocQuery(final String sqlSearch) {
String lowerCaseSQL = sqlSearch.toLowerCase();
for (String ddl : DDL_COMMANDS) {
if (lowerCaseSQL.contains(ddl)) {
throw new SQLInjectionException();
}
}
for (String comments : COMMENTS) {
if (lowerCaseSQL.contains(comments)) {
throw new SQLInjectionException();
@@ -55,7 +55,8 @@
org.apache.fineract.template.*,
org.apache.fineract.template.service.*,
org.apache.fineract.useradministration.*,
org.apache.fineract.batch">
org.apache.fineract.batch,
org.apache.fineract.adhocquery.*">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
@@ -80,6 +81,7 @@
<jpa:repositories base-package="org.apache.fineract.scheduledjobs.domain" />
<jpa:repositories base-package="org.apache.fineract.template.domain" />
<jpa:repositories base-package="org.apache.fineract.infrastructure.campaigns.sms.domain" />
<jpa:repositories base-package="org.apache.fineract.adhocquery.domain" />
<import resource="infrastructure.xml" />
@@ -0,0 +1,49 @@
--
-- 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.
--
CREATE TABLE `m_adhoc` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NULL DEFAULT NULL,
`query` VARCHAR(2000) NULL DEFAULT NULL,
`table_name` VARCHAR(100) NULL DEFAULT NULL,
`table_fields` VARCHAR(1000) NULL DEFAULT NULL,
`email` VARCHAR(500) NOT NULL,
`IsActive` TINYINT(1) NOT NULL DEFAULT '0',
`created_date` DATETIME NULL DEFAULT NULL,
`createdby_id` BIGINT NOT NULL,
`lastmodifiedby_id` BIGINT(20) NOT NULL,
`lastmodified_date` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `createdby_id` FOREIGN KEY (`createdby_id`) REFERENCES `m_appuser` (`id`),
CONSTRAINT `lastmodifiedby_id` FOREIGN KEY (`lastmodifiedby_id`) REFERENCES `m_appuser` (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
INSERT INTO `m_permission`
(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`) VALUES
('authorisation','UPDATE_ADHOC','ADHOC','UPDATE',1),
('authorisation','UPDATE_ADHOC_CHECKER','ADHOC','UPDATE',0),
('authorisation','DELETE_ADHOC','ADHOC','DELETE',1),
('authorisation','DELETE_ADHOC_CHECKER','ADHOC','DELETE',0),
('authorisation','CREATE_ADHOC','ADHOC','CREATE',1),
('authorisation','CREATE_ADHOC_CHECKER','ADHOC','CREATE',0);
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`) VALUES ('Generate AdhocClient Schedule', 'Generate AdhocClient Schedule', '0 0 12 1/1 * ? *', now());