Merge branch 'MIFOSX-1786' of git://github.com/binaryking/mifosx into binaryking-MIFOSX-1786

This commit is contained in:
Vishwas Babu A J
2015-01-13 11:10:16 -08:00
14 changed files with 2069 additions and 1895 deletions
+1035 -1029
View File
File diff suppressed because it is too large Load Diff
@@ -11,46 +11,52 @@ import java.util.Set;
public class HookApiConstants {
public static final String HOOK_RESOURCE_NAME = "HOOK";
public static final String HOOK_RESOURCE_NAME = "HOOK";
public static final String nameParamName = "name";
public static final String nameParamName = "name";
public static final String displayNameParamName = "displayName";
public static final String displayNameParamName = "displayName";
public static final String isActiveParamName = "isActive";
public static final String isActiveParamName = "isActive";
public static final String webTemplateName = "Web";
public static final String webTemplateName = "Web";
public static final String smsTemplateName = "SMS Bridge";
public static final String smsTemplateName = "SMS Bridge";
public static final String payloadURLName = "Payload URL";
public static final String payloadURLName = "Payload URL";
public static final String contentTypeName = "Content Type";
public static final String contentTypeName = "Content Type";
public static final String smsProviderName = "SMS Provider";
public static final String smsProviderName = "SMS Provider";
public static final String smsProviderAccountIdName = "SMS Provider Account Id";
public static final String smsProviderAccountIdName = "SMS Provider Account Id";
public static final String smsProviderTokenIdName = "SMS Provider Token";
public static final String smsProviderTokenIdName = "SMS Provider Token";
public static final String phoneNumberName = "Phone Number";
public static final String apiKeyName = "Api Key";
public static final String phoneNumberName = "Phone Number";
public static final String configParamName = "config";
public static final String apiKeyName = "Api Key";
public static final String eventsParamName = "events";
public static final String configParamName = "config";
public static final String entityNameParamName = "entityName";
public static final String eventsParamName = "events";
public static final String actionNameParamName = "actionName";
public static final String entityNameParamName = "entityName";
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(nameParamName, displayNameParamName,
isActiveParamName, configParamName, eventsParamName));
public static final String actionNameParamName = "actionName";
public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(nameParamName, displayNameParamName,
isActiveParamName, configParamName, eventsParamName));
public static final String templateIdParamName = "templateId";
public static final String templateNameParamName = "templateName";
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(nameParamName, displayNameParamName,
templateIdParamName, isActiveParamName, configParamName,
eventsParamName, templateNameParamName));
public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(nameParamName, displayNameParamName,
templateIdParamName, isActiveParamName, configParamName,
eventsParamName, templateNameParamName));
}
@@ -5,87 +5,95 @@
*/
package org.mifosplatform.infrastructure.hooks.data;
import org.joda.time.LocalDate;
import java.io.Serializable;
import java.util.List;
import org.joda.time.LocalDate;
public class HookData implements Serializable {
private final Long id;
private final String name;
private final String displayName;
private final Boolean isActive;
private final LocalDate createdAt;
private final LocalDate updatedAt;
private final Long id;
private final String name;
private final String displayName;
private final Boolean isActive;
private final LocalDate createdAt;
private final LocalDate updatedAt;
private final Long templateId;
private final String templateName;
// associations
private final List<Event> events;
private final List<Field> config;
// associations
private final List<Event> events;
private final List<Field> config;
// template data
private final List<HookTemplateData> templates;
private final List<Grouping> groupings;
// template data
private final List<HookTemplateData> templates;
private final List<Grouping> groupings;
public static HookData instance(final Long id, final String name,
final String displayName, final boolean isActive,
final LocalDate createdAt, final LocalDate updatedAt,
final List<Event> registeredEvents, final List<Field> config) {
return new HookData(id, name, displayName, isActive, createdAt,
updatedAt, registeredEvents, config, null, null);
}
public static HookData instance(final Long id, final String name,
final String displayName, final boolean isActive,
final LocalDate createdAt, final LocalDate updatedAt,
final Long templateId, final List<Event> registeredEvents,
final List<Field> config, final String templateName) {
return new HookData(id, name, displayName, isActive, createdAt,
updatedAt, templateId, registeredEvents, config, templateName,
null, null);
}
public static HookData template(final List<HookTemplateData> templates,
final List<Grouping> groupings) {
return new HookData(null, null, null, null, null, null, null, null,
templates, groupings);
}
public static HookData template(final List<HookTemplateData> templates,
final List<Grouping> groupings) {
return new HookData(null, null, null, null, null, null, null, null,
null, null, templates, groupings);
}
public static HookData templateExisting(final HookData hookData,
final List<HookTemplateData> templates,
final List<Grouping> groupings) {
return new HookData(hookData.id, hookData.name, hookData.displayName,
hookData.isActive, hookData.createdAt, hookData.updatedAt,
hookData.events, hookData.config, templates, groupings);
}
public static HookData templateExisting(final HookData hookData,
final List<HookTemplateData> templates,
final List<Grouping> groupings) {
return new HookData(hookData.id, hookData.name, hookData.displayName,
hookData.isActive, hookData.createdAt, hookData.updatedAt,
hookData.templateId, hookData.events, hookData.config,
hookData.templateName, templates, groupings);
}
private HookData(final Long id, final String name,
final String displayName, final Boolean isActive,
final LocalDate createdAt, final LocalDate updatedAt,
final List<Event> events, final List<Field> config,
final List<HookTemplateData> templates,
final List<Grouping> groupings) {
this.id = id;
this.name = name;
this.displayName = displayName;
this.isActive = isActive;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
private HookData(final Long id, final String name,
final String displayName, final Boolean isActive,
final LocalDate createdAt, final LocalDate updatedAt,
final Long templateId, final List<Event> events,
final List<Field> config, final String templateName,
final List<HookTemplateData> templates,
final List<Grouping> groupings) {
this.id = id;
this.name = name;
this.displayName = displayName;
this.isActive = isActive;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
this.templateId = templateId;
this.templateName = templateName;
// associations
this.events = events;
this.config = config;
// associations
this.events = events;
this.config = config;
// template
this.templates = templates;
this.groupings = groupings;
// template
this.templates = templates;
this.groupings = groupings;
}
}
public Long getHookId() {
return this.id;
}
public Long getHookId() {
return this.id;
}
public List<HookTemplateData> getTemplates() {
return this.templates;
}
public List<HookTemplateData> getTemplates() {
return this.templates;
}
public List<Grouping> getGroupings() {
return this.groupings;
}
public List<Grouping> getGroupings() {
return this.groupings;
}
public String getTemplateName() {
return this.name;
}
public String getTemplateName() {
return this.name;
}
}
@@ -5,183 +5,198 @@
*/
package org.mifosplatform.infrastructure.hooks.domain;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.configParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.displayNameParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.eventsParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.isActiveParamName;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.util.CollectionUtils;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import javax.persistence.*;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.*;
@Entity
@Table(name = "m_hook")
public class Hook extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "name", nullable = false, length = 100)
private String name;
@Column(name = "name", nullable = false, length = 100)
private String name;
@Column(name = "is_active", nullable = false)
private Boolean isActive;
@Column(name = "is_active", nullable = false)
private Boolean isActive;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "hook", orphanRemoval = true)
private Set<HookResource> events = new HashSet<>();
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "hook", orphanRemoval = true)
private Set<HookResource> events = new HashSet<>();
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "hook", orphanRemoval = true)
private Set<HookConfiguration> config = new HashSet<>();
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "hook", orphanRemoval = true)
private Set<HookConfiguration> config = new HashSet<>();
@ManyToOne(optional = true)
@JoinColumn(name = "template_id", referencedColumnName = "id", nullable = false)
private HookTemplate template;
@ManyToOne(optional = true)
@JoinColumn(name = "template_id", referencedColumnName = "id", nullable = false)
private HookTemplate template;
protected Hook() {
//
}
@ManyToOne(optional = true)
@JoinColumn(name = "ugd_template_id", referencedColumnName = "id", nullable = false)
private Template ugdTemplate;
public static Hook fromJson(final JsonCommand command,
final HookTemplate template, final Set<HookConfiguration> config,
final Set<HookResource> events) {
final String displayName = command
.stringValueOfParameterNamed(displayNameParamName);
Boolean isActive = command
.booleanObjectValueOfParameterNamed(isActiveParamName);
if(isActive == null)
protected Hook() {
//
}
public static Hook fromJson(final JsonCommand command,
final HookTemplate template, final Set<HookConfiguration> config,
final Set<HookResource> events, final Template ugdTemplate) {
final String displayName = command
.stringValueOfParameterNamed(displayNameParamName);
Boolean isActive = command
.booleanObjectValueOfParameterNamed(isActiveParamName);
if (isActive == null)
isActive = false;
return new Hook(template, displayName, isActive, config, events);
}
return new Hook(template, displayName, isActive, config, events,
ugdTemplate);
}
private Hook(final HookTemplate template, final String displayName,
final Boolean isActive, final Set<HookConfiguration> config,
final Set<HookResource> events) {
private Hook(final HookTemplate template, final String displayName,
final Boolean isActive, final Set<HookConfiguration> config,
final Set<HookResource> events, final Template ugdTemplate) {
this.template = template;
this.template = template;
if (StringUtils.isNotBlank(displayName)) {
this.name = displayName.trim();
} else {
this.name = template.getName();
}
this.isActive = isActive;
if (!CollectionUtils.isEmpty(config)) {
this.config = associateConfigWithThisHook(config);
}
if (!CollectionUtils.isEmpty(events)) {
this.events = associateEventsWithThisHook(events);
}
if (StringUtils.isNotBlank(displayName)) {
this.name = displayName.trim();
} else {
this.name = template.getName();
}
this.isActive = isActive;
if (!CollectionUtils.isEmpty(config)) {
this.config = associateConfigWithThisHook(config);
}
if (!CollectionUtils.isEmpty(events)) {
this.events = associateEventsWithThisHook(events);
}
}
this.ugdTemplate = ugdTemplate;
}
private Set<HookConfiguration> associateConfigWithThisHook(
final Set<HookConfiguration> config) {
for (final HookConfiguration hookConfiguration : config) {
hookConfiguration.update(this);
}
return config;
}
private Set<HookConfiguration> associateConfigWithThisHook(
final Set<HookConfiguration> config) {
for (final HookConfiguration hookConfiguration : config) {
hookConfiguration.update(this);
}
return config;
}
private Set<HookResource> associateEventsWithThisHook(
final Set<HookResource> events) {
for (final HookResource hookResource : events) {
hookResource.update(this);
}
return events;
}
private Set<HookResource> associateEventsWithThisHook(
final Set<HookResource> events) {
for (final HookResource hookResource : events) {
hookResource.update(this);
}
return events;
}
public HookTemplate getHookTemplate() {
return this.template;
}
public HookTemplate getHookTemplate() {
return this.template;
}
public Set<HookConfiguration> getHookConfig() {
return this.config;
}
public Template getUgdTemplate() {
return this.ugdTemplate;
}
public Map<String, Object> update(final JsonCommand command) {
public Long getUgdTemplateId() {
return this.ugdTemplate.getId();
}
final Map<String, Object> actualChanges = new LinkedHashMap<>(4);
public Set<HookConfiguration> getHookConfig() {
return this.config;
}
if (command.isChangeInStringParameterNamed(displayNameParamName,
this.name)) {
final String newValue = command
.stringValueOfParameterNamed(displayNameParamName);
actualChanges.put(displayNameParamName, newValue);
this.name = newValue;
}
public Map<String, Object> update(final JsonCommand command) {
if (command.isChangeInBooleanParameterNamed(isActiveParamName,
this.isActive)) {
final Boolean newValue = command
.booleanObjectValueOfParameterNamed(isActiveParamName);
actualChanges.put(isActiveParamName, newValue);
this.isActive = newValue;
}
final Map<String, Object> actualChanges = new LinkedHashMap<>(5);
// events
if (command.hasParameter(eventsParamName)) {
final JsonArray jsonArray = command
.arrayOfParameterNamed(eventsParamName);
if (jsonArray != null) {
actualChanges.put(eventsParamName, jsonArray);
}
}
if (command.isChangeInStringParameterNamed(displayNameParamName,
this.name)) {
final String newValue = command
.stringValueOfParameterNamed(displayNameParamName);
actualChanges.put(displayNameParamName, newValue);
this.name = newValue;
}
// config
if (command.hasParameter(configParamName)) {
final JsonElement element = command.parsedJson().getAsJsonObject()
.get(configParamName);
if (element != null) {
actualChanges.put(configParamName, element);
}
}
if (command.isChangeInBooleanParameterNamed(isActiveParamName,
this.isActive)) {
final Boolean newValue = command
.booleanObjectValueOfParameterNamed(isActiveParamName);
actualChanges.put(isActiveParamName, newValue);
this.isActive = newValue;
}
return actualChanges;
}
if (command.isChangeInLongParameterNamed(templateIdParamName,
getUgdTemplateId())) {
final Long newValue = command
.longValueOfParameterNamed(templateIdParamName);
actualChanges.put(templateIdParamName, newValue);
}
public boolean updateEvents(final Set<HookResource> newHookEvents) {
if (newHookEvents == null) {
return false;
}
// events
if (command.hasParameter(eventsParamName)) {
final JsonArray jsonArray = command
.arrayOfParameterNamed(eventsParamName);
if (jsonArray != null) {
actualChanges.put(eventsParamName, jsonArray);
}
}
if (this.events == null) {
this.events = new HashSet<>();
}
this.events.clear();
this.events.addAll(associateEventsWithThisHook(newHookEvents));
return true;
}
// config
if (command.hasParameter(configParamName)) {
final JsonElement element = command.parsedJson().getAsJsonObject()
.get(configParamName);
if (element != null) {
actualChanges.put(configParamName, element);
}
}
public boolean updateConfig(final Set<HookConfiguration> newHookConfig) {
if (newHookConfig == null) {
return false;
}
return actualChanges;
}
if (this.config == null) {
this.config = new HashSet<>();
}
this.config.clear();
this.config.addAll(associateConfigWithThisHook(newHookConfig));
return true;
}
public boolean updateEvents(final Set<HookResource> newHookEvents) {
if (newHookEvents == null) {
return false;
}
if (this.events == null) {
this.events = new HashSet<>();
}
this.events.clear();
this.events.addAll(associateEventsWithThisHook(newHookEvents));
return true;
}
public boolean updateConfig(final Set<HookConfiguration> newHookConfig) {
if (newHookConfig == null) {
return false;
}
if (this.config == null) {
this.config = new HashSet<>();
}
this.config.clear();
this.config.addAll(associateConfigWithThisHook(newHookConfig));
return true;
}
public void updateUgdTemplate(final Template ugdTemplate) {
this.ugdTemplate = ugdTemplate;
}
}
@@ -5,8 +5,6 @@
*/
package org.mifosplatform.infrastructure.hooks.listener;
import java.util.List;
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.infrastructure.hooks.domain.Hook;
@@ -20,48 +18,50 @@ import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MifosHookListener implements HookListener {
private final HookProcessorProvider hookProcessorProvider;
private final HookReadPlatformService hookReadPlatformService;
private final TenantDetailsService tenantDetailsService;
private final HookProcessorProvider hookProcessorProvider;
private final HookReadPlatformService hookReadPlatformService;
private final TenantDetailsService tenantDetailsService;
@Autowired
public MifosHookListener(final HookProcessorProvider hookProcessorProvider,
final HookReadPlatformService hookReadPlatformService,
final TenantDetailsService tenantDetailsService) {
this.hookReadPlatformService = hookReadPlatformService;
this.hookProcessorProvider = hookProcessorProvider;
this.tenantDetailsService = tenantDetailsService;
}
@Autowired
public MifosHookListener(final HookProcessorProvider hookProcessorProvider,
final HookReadPlatformService hookReadPlatformService,
final TenantDetailsService tenantDetailsService) {
this.hookReadPlatformService = hookReadPlatformService;
this.hookProcessorProvider = hookProcessorProvider;
this.tenantDetailsService = tenantDetailsService;
}
@Override
public void onApplicationEvent(final HookEvent event) {
@Override
public void onApplicationEvent(final HookEvent event) {
final String tenantIdentifier = event.getTenantIdentifier();
final MifosPlatformTenant tenant = this.tenantDetailsService
.loadTenantById(tenantIdentifier);
ThreadLocalContextUtil.setTenant(tenant);
final String tenantIdentifier = event.getTenantIdentifier();
final MifosPlatformTenant tenant = this.tenantDetailsService
.loadTenantById(tenantIdentifier);
ThreadLocalContextUtil.setTenant(tenant);
final AppUser appUser = event.getAppUser();
final String authToken = event.getAuthToken();
final AppUser appUser = event.getAppUser();
final String authToken = event.getAuthToken();
final HookEventSource hookEventSource = event.getSource();
final String entityName = hookEventSource.getEntityName();
final String actionName = hookEventSource.getActionName();
final String payload = event.getPayload();
final List<Hook> hooks = this.hookReadPlatformService
.retrieveHooksByEvent(hookEventSource.getEntityName(),
hookEventSource.getActionName());
final HookEventSource hookEventSource = event.getSource();
final String entityName = hookEventSource.getEntityName();
final String actionName = hookEventSource.getActionName();
final String payload = event.getPayload();
for (final Hook hook : hooks) {
final HookProcessor processor = this.hookProcessorProvider
.getProcessor(hook);
processor.process(hook, appUser, payload, entityName, actionName,
tenantIdentifier, authToken);
}
}
final List<Hook> hooks = this.hookReadPlatformService
.retrieveHooksByEvent(hookEventSource.getEntityName(),
hookEventSource.getActionName());
for (final Hook hook : hooks) {
final HookProcessor processor = this.hookProcessorProvider
.getProcessor(hook);
processor.process(hook, appUser, payload, entityName, actionName,
tenantIdentifier, authToken);
}
}
}
@@ -5,79 +5,131 @@
*/
package org.mifosplatform.infrastructure.hooks.processor;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.apiKeyName;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import org.mifosplatform.infrastructure.hooks.domain.Hook;
import org.mifosplatform.infrastructure.hooks.domain.HookConfiguration;
import org.mifosplatform.infrastructure.hooks.domain.HookConfigurationRepository;
import org.mifosplatform.infrastructure.hooks.processor.data.SmsProviderData;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.template.service.TemplateMergeService;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import retrofit.Callback;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.apiKeyName;
@Service
public class TwilioHookProcessor implements HookProcessor {
private final HookConfigurationRepository hookConfigurationRepository;
private final HookConfigurationRepository hookConfigurationRepository;
private final TemplateMergeService templateMergeService;
private final ClientRepository clientRepository;
@Autowired
public TwilioHookProcessor(
final HookConfigurationRepository hookConfigurationRepository) {
this.hookConfigurationRepository = hookConfigurationRepository;
}
@Autowired
public TwilioHookProcessor(
final HookConfigurationRepository hookConfigurationRepository,
final TemplateMergeService templateMergeService,
final ClientRepository clientRepository) {
this.hookConfigurationRepository = hookConfigurationRepository;
this.templateMergeService = templateMergeService;
this.clientRepository = clientRepository;
}
@Override
public void process(final Hook hook,
@SuppressWarnings("unused") final AppUser appUser,
final String payload, final String entityName,
final String actionName, final String tenantIdentifier,
final String authToken) {
@Override
public void process(final Hook hook,
@SuppressWarnings("unused") final AppUser appUser,
final String payload, final String entityName,
final String actionName, final String tenantIdentifier,
final String authToken) {
final SmsProviderData smsProviderData = new SmsProviderData(
hook.getHookConfig());
final SmsProviderData smsProviderData = new SmsProviderData(
hook.getHookConfig());
sendRequest(smsProviderData, payload, entityName, actionName,
tenantIdentifier, authToken, hook);
}
sendRequest(smsProviderData, payload, entityName, actionName,
tenantIdentifier, authToken, hook);
}
@SuppressWarnings("unchecked")
private void sendRequest(final SmsProviderData smsProviderData,
final String payload, final String entityName,
final String actionName, final String tenantIdentifier,
final String authToken, final Hook hook) {
@SuppressWarnings("unchecked")
private void sendRequest(final SmsProviderData smsProviderData,
final String payload, String entityName, String actionName,
final String tenantIdentifier, final String authToken,
final Hook hook) {
final WebHookService service = ProcessorHelper
.createWebHookService(smsProviderData.getUrl());
final WebHookService service = ProcessorHelper
.createWebHookService(smsProviderData.getUrl());
@SuppressWarnings("rawtypes")
final Callback callback = ProcessorHelper
.createCallback(smsProviderData.getUrl());
@SuppressWarnings("rawtypes")
final Callback callback = ProcessorHelper
.createCallback(smsProviderData.getUrl());
String apiKey = this.hookConfigurationRepository
.findOneByHookIdAndFieldName(hook.getId(), apiKeyName);
if (apiKey == null) {
smsProviderData.setUrl(null);
smsProviderData.setEndpoint(System.getProperty("baseUrl"));
smsProviderData.setTenantId(tenantIdentifier);
smsProviderData.setMifosToken(authToken);
apiKey = service.sendSmsBridgeConfigRequest(smsProviderData);
final HookConfiguration apiKeyEntry = HookConfiguration.createNew(
hook, "string", apiKeyName, apiKey);
this.hookConfigurationRepository.save(apiKeyEntry);
}
String apiKey = this.hookConfigurationRepository
.findOneByHookIdAndFieldName(hook.getId(), apiKeyName);
if (apiKey == null) {
smsProviderData.setUrl(null);
smsProviderData.setEndpoint(System.getProperty("baseUrl"));
smsProviderData.setTenantId(tenantIdentifier);
smsProviderData.setMifosToken(authToken);
apiKey = service.sendSmsBridgeConfigRequest(smsProviderData);
final HookConfiguration apiKeyEntry = HookConfiguration.createNew(
hook, "string", apiKeyName, apiKey);
this.hookConfigurationRepository.save(apiKeyEntry);
}
if (apiKey != null && !apiKey.equals("")) {
final JsonObject json = new JsonParser().parse(payload)
.getAsJsonObject();
service.sendSmsBridgeRequest(entityName, actionName,
tenantIdentifier, apiKey, json, callback);
}
if (apiKey != null && !apiKey.equals("")) {
JsonObject json = null;
if (hook.getUgdTemplate() != null) {
entityName = "sms";
actionName = "send";
json = processUgdTemplate(payload, hook, authToken);
if (json == null) {
return;
}
} else {
json = new JsonParser().parse(payload).getAsJsonObject();
}
service.sendSmsBridgeRequest(entityName, actionName,
tenantIdentifier, apiKey, json, callback);
}
}
}
private JsonObject processUgdTemplate(final String payload,
final Hook hook, final String authToken) {
JsonObject json = null;
try {
@SuppressWarnings("unchecked")
final HashMap<String, Object> map = new ObjectMapper().readValue(
payload, HashMap.class);
map.put("BASE_URI", System.getProperty("baseUrl"));
if (map.containsKey("clientId")) {
final Long clientId = new Long(Integer.toString((int) map
.get("clientId")));
final Client client = this.clientRepository.findOne(clientId);
final String mobileNo = client.mobileNo();
if (mobileNo != null && !mobileNo.isEmpty()) {
this.templateMergeService.setAuthToken(authToken);
final String compiledMessage = this.templateMergeService
.compile(hook.getUgdTemplate(), map)
.replace("<p>", "").replace("</p>", "");
final Map<String, String> jsonMap = new HashMap<>();
jsonMap.put("mobileNo", mobileNo);
jsonMap.put("message", compiledMessage);
final String jsonString = new Gson().toJson(jsonMap);
json = new JsonParser().parse(jsonString).getAsJsonObject();
}
}
} catch (IOException e) {
}
return json;
}
}
@@ -5,98 +5,112 @@
*/
package org.mifosplatform.infrastructure.hooks.serialization;
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 com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.hooks.api.HookApiConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.*;
@Component
public class HookCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<>(
Arrays.asList("name", "displayName", "isActive", "events", "config"));
private final FromJsonHelper fromApiJsonHelper;
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<>(
Arrays.asList("name", "displayName", "isActive", "events",
"config", "templateId"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public HookCommandFromApiJsonDeserializer(
final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Autowired
public HookCommandFromApiJsonDeserializer(
final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForCreate(final String json) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
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 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("hook");
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("hook");
final JsonElement element = this.fromApiJsonHelper.parse(json);
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 name = this.fromApiJsonHelper.extractStringNamed("name",
element);
baseDataValidator.reset().parameter("name").value(name).notBlank()
.notExceedingLengthOf(100);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
if (this.fromApiJsonHelper.parameterExists(
HookApiConstants.templateIdParamName, element)) {
final Long templateId = this.fromApiJsonHelper.extractLongNamed(
HookApiConstants.templateIdParamName, element);
baseDataValidator.reset()
.parameter(HookApiConstants.templateIdParamName)
.value(templateId).notNull().integerGreaterThanZero();
}
public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
this.supportedParameters);
public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("hook");
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
this.supportedParameters);
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);
}
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("hook");
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
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);
}
private void throwExceptionIfValidationWarningsExist(
final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
if (this.fromApiJsonHelper.parameterExists(
HookApiConstants.templateIdParamName, element)) {
final Long templateId = this.fromApiJsonHelper.extractLongNamed(
HookApiConstants.templateIdParamName, element);
baseDataValidator.reset()
.parameter(HookApiConstants.templateIdParamName)
.value(templateId).notNull().integerGreaterThanZero();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(
final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
}
@@ -5,20 +5,10 @@
*/
package org.mifosplatform.infrastructure.hooks.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.hooks.data.Event;
import org.mifosplatform.infrastructure.hooks.data.EventResultSetExtractor;
import org.mifosplatform.infrastructure.hooks.data.Field;
import org.mifosplatform.infrastructure.hooks.data.Grouping;
import org.mifosplatform.infrastructure.hooks.data.HookData;
import org.mifosplatform.infrastructure.hooks.data.HookTemplateData;
import org.mifosplatform.infrastructure.hooks.data.*;
import org.mifosplatform.infrastructure.hooks.domain.Hook;
import org.mifosplatform.infrastructure.hooks.domain.HookRepository;
import org.mifosplatform.infrastructure.hooks.exception.HookNotFoundException;
@@ -30,227 +20,238 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
@Service
public class HookReadPlatformServiceImpl implements HookReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final HookRepository hookRepository;
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
private final HookRepository hookRepository;
private final PlatformSecurityContext context;
@Autowired
public HookReadPlatformServiceImpl(final PlatformSecurityContext context,
final HookRepository hookRepository,
final RoutingDataSource dataSource) {
this.context = context;
this.hookRepository = hookRepository;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Autowired
public HookReadPlatformServiceImpl(final PlatformSecurityContext context,
final HookRepository hookRepository,
final RoutingDataSource dataSource) {
this.context = context;
this.hookRepository = hookRepository;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Collection<HookData> retrieveAllHooks() {
this.context.authenticatedUser();
final HookMapper rm = new HookMapper(this.jdbcTemplate);
final String sql = "select " + rm.schema() + " order by h.name";
@Override
public Collection<HookData> retrieveAllHooks() {
this.context.authenticatedUser();
final HookMapper rm = new HookMapper(this.jdbcTemplate);
final String sql = "select " + rm.schema() + " order by h.name";
return this.jdbcTemplate.query(sql, rm, new Object[] {});
}
return this.jdbcTemplate.query(sql, rm, new Object[]{});
}
@Override
public HookData retrieveHook(final Long hookId) {
try {
this.context.authenticatedUser();
final HookMapper rm = new HookMapper(this.jdbcTemplate);
final String sql = "select " + rm.schema() + " where h.id = ?";
@Override
public HookData retrieveHook(final Long hookId) {
try {
this.context.authenticatedUser();
final HookMapper rm = new HookMapper(this.jdbcTemplate);
final String sql = "select " + rm.schema() + " where h.id = ?";
return this.jdbcTemplate.queryForObject(sql, rm,
new Object[] { hookId });
} catch (final EmptyResultDataAccessException e) {
throw new HookNotFoundException(hookId);
}
return this.jdbcTemplate.queryForObject(sql, rm,
new Object[]{hookId});
} catch (final EmptyResultDataAccessException e) {
throw new HookNotFoundException(hookId);
}
}
}
@Override
@Cacheable(value = "hooks", key = "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat('HK')")
public List<Hook> retrieveHooksByEvent(final String actionName,
final String entityName) {
@Override
@Cacheable(value = "hooks", key = "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat('HK')")
public List<Hook> retrieveHooksByEvent(final String actionName,
final String entityName) {
return this.hookRepository.findAllHooksListeningToEvent(actionName,
entityName);
}
return this.hookRepository.findAllHooksListeningToEvent(actionName,
entityName);
}
@Override
public HookData retrieveNewHookDetails(final String templateName) {
@Override
public HookData retrieveNewHookDetails(final String templateName) {
this.context.authenticatedUser();
final TemplateMapper rm = new TemplateMapper(this.jdbcTemplate);
final String sql;
List<HookTemplateData> templateData;
this.context.authenticatedUser();
final TemplateMapper rm = new TemplateMapper(this.jdbcTemplate);
final String sql;
List<HookTemplateData> templateData;
if (templateName == null) {
sql = "select " + rm.schema() + " order by s.name";
templateData = this.jdbcTemplate.query(sql, rm, new Object[] {});
} else {
sql = "select " + rm.schema() + " where s.name = ? order by s.name";
templateData = this.jdbcTemplate.query(sql, rm,
new Object[] { templateName });
}
if (templateName == null) {
sql = "select " + rm.schema() + " order by s.name";
templateData = this.jdbcTemplate.query(sql, rm, new Object[]{});
} else {
sql = "select " + rm.schema() + " where s.name = ? order by s.name";
templateData = this.jdbcTemplate.query(sql, rm,
new Object[]{templateName});
}
final List<Grouping> events = getTemplateForEvents();
final List<Grouping> events = getTemplateForEvents();
return HookData.template(templateData, events);
}
return HookData.template(templateData, events);
}
private List<Grouping> getTemplateForEvents() {
final String sql = "select p.grouping, p.entity_name, p.action_name from m_permission p "
+ " where p.action_name NOT LIKE '%CHECKER%' AND p.action_name NOT LIKE '%READ%' "
+ " order by p.grouping, p.entity_name ";
final EventResultSetExtractor extractor = new EventResultSetExtractor();
return this.jdbcTemplate.query(sql, extractor);
}
private List<Grouping> getTemplateForEvents() {
final String sql = "select p.grouping, p.entity_name, p.action_name from m_permission p "
+ " where p.action_name NOT LIKE '%CHECKER%' AND p.action_name NOT LIKE '%READ%' "
+ " order by p.grouping, p.entity_name ";
final EventResultSetExtractor extractor = new EventResultSetExtractor();
return this.jdbcTemplate.query(sql, extractor);
}
private static final class HookMapper implements RowMapper<HookData> {
private static final class HookMapper implements RowMapper<HookData> {
private final JdbcTemplate jdbcTemplate;
private final JdbcTemplate jdbcTemplate;
public HookMapper(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public HookMapper(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public String schema() {
return " h.id, s.name as name, h.name as display_name, h.is_active, h.created_date, h.lastmodified_date "
+ " from m_hook h inner join m_hook_templates s on h.template_id = s.id ";
}
public String schema() {
return " h.id, s.name as name, h.name as display_name, h.is_active, h.created_date,"
+ " h.lastmodified_date, h.ugd_template_id, tp.name as ugd_template_name, "
+ "h.ugd_template_id from m_hook h inner join m_hook_templates s on h.template_id = s.id"
+ " inner join m_template tp on h.ugd_template_id = tp.id";
}
@Override
public HookData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
@Override
public HookData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String displayname = rs.getString("display_name");
final boolean isActive = rs.getBoolean("is_active");
final LocalDate createdAt = JdbcSupport.getLocalDate(rs,
"created_date");
final LocalDate updatedAt = JdbcSupport.getLocalDate(rs,
"lastmodified_date");
final List<Event> registeredEvents = retrieveEvents(id);
final List<Field> config = retrieveConfig(id);
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String displayname = rs.getString("display_name");
final boolean isActive = rs.getBoolean("is_active");
final LocalDate createdAt = JdbcSupport.getLocalDate(rs,
"created_date");
final LocalDate updatedAt = JdbcSupport.getLocalDate(rs,
"lastmodified_date");
final Long templateId = rs.getLong("ugd_template_id");
final String templateName = rs.getString("ugd_template_name");
final List<Event> registeredEvents = retrieveEvents(id);
final List<Field> config = retrieveConfig(id);
return HookData.instance(id, name, displayname, isActive,
createdAt, updatedAt, registeredEvents, config);
}
return HookData.instance(id, name, displayname, isActive,
createdAt, updatedAt, templateId, registeredEvents, config,
templateName);
}
private List<Event> retrieveEvents(final Long hookId) {
private List<Event> retrieveEvents(final Long hookId) {
final HookEventMapper rm = new HookEventMapper();
final String sql = "select " + rm.schema() + " where h.id= ?";
final HookEventMapper rm = new HookEventMapper();
final String sql = "select " + rm.schema() + " where h.id= ?";
return this.jdbcTemplate.query(sql, rm, new Object[] { hookId });
}
return this.jdbcTemplate.query(sql, rm, new Object[]{hookId});
}
private List<Field> retrieveConfig(final Long hookId) {
private List<Field> retrieveConfig(final Long hookId) {
final HookConfigMapper rm = new HookConfigMapper();
final String sql = "select " + rm.schema()
+ " where h.id= ? order by hc.field_name";
final HookConfigMapper rm = new HookConfigMapper();
final String sql = "select " + rm.schema()
+ " where h.id= ? order by hc.field_name";
final List<Field> fields = this.jdbcTemplate.query(sql, rm,
new Object[] { hookId });
final List<Field> fields = this.jdbcTemplate.query(sql, rm,
new Object[]{hookId});
return fields;
}
}
return fields;
}
}
private static final class HookEventMapper implements RowMapper<Event> {
private static final class HookEventMapper implements RowMapper<Event> {
public String schema() {
return " re.action_name, re.entity_name from m_hook h inner join m_hook_registered_events re on h.id = re.hook_id ";
}
public String schema() {
return " re.action_name, re.entity_name from m_hook h inner join m_hook_registered_events re on h.id = re.hook_id ";
}
@Override
public Event mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final String actionName = rs.getString("action_name");
final String entityName = rs.getString("entity_name");
return Event.instance(actionName, entityName);
}
}
@Override
public Event mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final String actionName = rs.getString("action_name");
final String entityName = rs.getString("entity_name");
return Event.instance(actionName, entityName);
}
}
private static final class HookConfigMapper implements RowMapper<Field> {
private static final class HookConfigMapper implements RowMapper<Field> {
public String schema() {
return " hc.field_name, hc.field_value from m_hook h inner join m_hook_configuration hc on h.id = hc.hook_id ";
}
public String schema() {
return " hc.field_name, hc.field_value from m_hook h inner join m_hook_configuration hc on h.id = hc.hook_id ";
}
@Override
public Field mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final String fieldName = rs.getString("field_name");
final String fieldValue = rs.getString("field_value");
return Field.fromConfig(fieldName, fieldValue);
}
}
@Override
public Field mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final String fieldName = rs.getString("field_name");
final String fieldValue = rs.getString("field_value");
return Field.fromConfig(fieldName, fieldValue);
}
}
private static final class TemplateMapper implements
RowMapper<HookTemplateData> {
private static final class TemplateMapper
implements
RowMapper<HookTemplateData> {
private final JdbcTemplate jdbcTemplate;
private final JdbcTemplate jdbcTemplate;
public TemplateMapper(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public TemplateMapper(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public String schema() {
return " s.id, s.name from m_hook_templates s ";
}
public String schema() {
return " s.id, s.name from m_hook_templates s ";
}
@Override
public HookTemplateData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
@Override
public HookTemplateData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final List<Field> schema = retrieveSchema(id);
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final List<Field> schema = retrieveSchema(id);
return HookTemplateData.instance(id, name, schema);
}
return HookTemplateData.instance(id, name, schema);
}
private List<Field> retrieveSchema(final Long templateId) {
private List<Field> retrieveSchema(final Long templateId) {
final TemplateSchemaMapper rm = new TemplateSchemaMapper();
final String sql = "select " + rm.schema()
+ " where s.id= ? order by hs.field_name ";
final TemplateSchemaMapper rm = new TemplateSchemaMapper();
final String sql = "select " + rm.schema()
+ " where s.id= ? order by hs.field_name ";
final List<Field> fields = this.jdbcTemplate.query(sql, rm,
new Object[] { templateId });
final List<Field> fields = this.jdbcTemplate.query(sql, rm,
new Object[]{templateId});
return fields;
}
}
return fields;
}
}
private static final class TemplateSchemaMapper implements RowMapper<Field> {
private static final class TemplateSchemaMapper implements RowMapper<Field> {
public String schema() {
return " hs.field_type, hs.field_name, hs.placeholder, hs.optional from m_hook_templates s "
+ " inner join m_hook_schema hs on s.id = hs.hook_template_id ";
}
public String schema() {
return " hs.field_type, hs.field_name, hs.placeholder, hs.optional from m_hook_templates s "
+ " inner join m_hook_schema hs on s.id = hs.hook_template_id ";
}
@Override
public Field mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final String fieldName = rs.getString("field_name");
final String fieldType = rs.getString("field_type");
final Boolean optional = rs.getBoolean("optional");
final String placeholder = rs.getString("placeholder");
return Field
.fromSchema(fieldType, fieldName, optional, placeholder);
}
}
@Override
public Field mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum)
throws SQLException {
final String fieldName = rs.getString("field_name");
final String fieldType = rs.getString("field_type");
final Boolean optional = rs.getBoolean("optional");
final String placeholder = rs.getString("placeholder");
return Field
.fromSchema(fieldType, fieldName, optional, placeholder);
}
}
}
@@ -5,22 +5,8 @@
*/
package org.mifosplatform.infrastructure.hooks.service;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.actionNameParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.configParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.contentTypeName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.entityNameParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.eventsParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.nameParamName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.payloadURLName;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.webTemplateName;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
@@ -29,313 +15,338 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.hooks.domain.Hook;
import org.mifosplatform.infrastructure.hooks.domain.HookConfiguration;
import org.mifosplatform.infrastructure.hooks.domain.HookRepository;
import org.mifosplatform.infrastructure.hooks.domain.HookResource;
import org.mifosplatform.infrastructure.hooks.domain.HookTemplate;
import org.mifosplatform.infrastructure.hooks.domain.HookTemplateRepository;
import org.mifosplatform.infrastructure.hooks.domain.Schema;
import org.mifosplatform.infrastructure.hooks.domain.*;
import org.mifosplatform.infrastructure.hooks.exception.HookNotFoundException;
import org.mifosplatform.infrastructure.hooks.exception.HookTemplateNotFoundException;
import org.mifosplatform.infrastructure.hooks.processor.ProcessorHelper;
import org.mifosplatform.infrastructure.hooks.processor.WebHookService;
import org.mifosplatform.infrastructure.hooks.serialization.HookCommandFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateRepository;
import org.mifosplatform.template.exception.TemplateNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import retrofit.RetrofitError;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.*;
import java.util.Map.Entry;
import static org.mifosplatform.infrastructure.hooks.api.HookApiConstants.*;
@Service
public class HookWritePlatformServiceJpaRepositoryImpl implements
HookWritePlatformService {
public class HookWritePlatformServiceJpaRepositoryImpl
implements
HookWritePlatformService {
private final PlatformSecurityContext context;
private final HookRepository hookRepository;
private final HookTemplateRepository hookTemplateRepository;
private final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final FromJsonHelper fromApiJsonHelper;
private final PlatformSecurityContext context;
private final HookRepository hookRepository;
private final HookTemplateRepository hookTemplateRepository;
private final TemplateRepository ugdTemplateRepository;
private final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public HookWritePlatformServiceJpaRepositoryImpl(
final PlatformSecurityContext context,
final HookRepository hookRepository,
final HookTemplateRepository hookTemplateRepository,
final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final FromJsonHelper fromApiJsonHelper) {
this.context = context;
this.hookRepository = hookRepository;
this.hookTemplateRepository = hookTemplateRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Autowired
public HookWritePlatformServiceJpaRepositoryImpl(
final PlatformSecurityContext context,
final HookRepository hookRepository,
final HookTemplateRepository hookTemplateRepository,
final TemplateRepository ugdTemplateRepository,
final HookCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final FromJsonHelper fromApiJsonHelper) {
this.context = context;
this.hookRepository = hookRepository;
this.hookTemplateRepository = hookTemplateRepository;
this.ugdTemplateRepository = ugdTemplateRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Transactional
@Override
@CacheEvict(value = "hooks", allEntries = true)
public CommandProcessingResult createHook(final JsonCommand command) {
@Transactional
@Override
@CacheEvict(value = "hooks", allEntries = true)
public CommandProcessingResult createHook(final JsonCommand command) {
try {
this.context.authenticatedUser();
try {
this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForCreate(command.json());
this.fromApiJsonDeserializer.validateForCreate(command.json());
final HookTemplate template = retrieveHookTemplateBy(command
.stringValueOfParameterNamed(nameParamName));
final String configJson = command.jsonFragment(configParamName);
final Set<HookConfiguration> config = assembleConfig(
command.mapValueOfParameterNamed(configJson), template);
final JsonArray events = command
.arrayOfParameterNamed(eventsParamName);
final Set<HookResource> allEvents = assembleSetOfEvents(events);
final Hook hook = Hook.fromJson(command, template, config,
allEvents);
final HookTemplate template = retrieveHookTemplateBy(command
.stringValueOfParameterNamed(nameParamName));
final String configJson = command.jsonFragment(configParamName);
final Set<HookConfiguration> config = assembleConfig(
command.mapValueOfParameterNamed(configJson), template);
final JsonArray events = command
.arrayOfParameterNamed(eventsParamName);
final Set<HookResource> allEvents = assembleSetOfEvents(events);
Template ugdTemplate = null;
if (command.hasParameter(templateIdParamName)) {
final Long ugdTemplateId = command
.longValueOfParameterNamed(templateIdParamName);
ugdTemplate = this.ugdTemplateRepository.findOne(ugdTemplateId);
if (ugdTemplate == null) {
throw new TemplateNotFoundException(ugdTemplateId);
}
}
final Hook hook = Hook.fromJson(command, template, config,
allEvents, ugdTemplate);
validateHookRules(template, config, allEvents);
validateHookRules(template, config, allEvents);
this.hookRepository.save(hook);
this.hookRepository.save(hook);
return new CommandProcessingResultBuilder()
.withCommandId(command.commandId())
.withEntityId(hook.getId()).build();
} catch (final DataIntegrityViolationException dve) {
handleHookDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
return new CommandProcessingResultBuilder()
.withCommandId(command.commandId())
.withEntityId(hook.getId()).build();
} catch (final DataIntegrityViolationException dve) {
handleHookDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
@CacheEvict(value = "hooks", allEntries = true)
public CommandProcessingResult updateHook(final Long hookId,
final JsonCommand command) {
@Transactional
@Override
@CacheEvict(value = "hooks", allEntries = true)
public CommandProcessingResult updateHook(final Long hookId,
final JsonCommand command) {
try {
this.context.authenticatedUser();
try {
this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForUpdate(command.json());
this.fromApiJsonDeserializer.validateForUpdate(command.json());
final Hook hook = retrieveHookBy(hookId);
final HookTemplate template = hook.getHookTemplate();
final Map<String, Object> changes = hook.update(command);
final Hook hook = retrieveHookBy(hookId);
final HookTemplate template = hook.getHookTemplate();
final Map<String, Object> changes = hook.update(command);
if (!changes.isEmpty()) {
if (!changes.isEmpty()) {
if (changes.containsKey(eventsParamName)) {
final Set<HookResource> events = assembleSetOfEvents(command
.arrayOfParameterNamed(eventsParamName));
final boolean updated = hook.updateEvents(events);
if (!updated) {
changes.remove(eventsParamName);
}
}
if (changes.containsKey(templateIdParamName)) {
final Long ugdTemplateId = command
.longValueOfParameterNamed(templateIdParamName);
final Template ugdTemplate = this.ugdTemplateRepository
.findOne(ugdTemplateId);
if (ugdTemplate == null) {
changes.remove(templateIdParamName);
throw new TemplateNotFoundException(ugdTemplateId);
}
hook.updateUgdTemplate(ugdTemplate);
}
if (changes.containsKey(configParamName)) {
final String configJson = command
.jsonFragment(configParamName);
final Set<HookConfiguration> config = assembleConfig(
command.mapValueOfParameterNamed(configJson),
template);
final boolean updated = hook.updateConfig(config);
if (!updated) {
changes.remove(configParamName);
}
}
if (changes.containsKey(eventsParamName)) {
final Set<HookResource> events = assembleSetOfEvents(command
.arrayOfParameterNamed(eventsParamName));
final boolean updated = hook.updateEvents(events);
if (!updated) {
changes.remove(eventsParamName);
}
}
this.hookRepository.saveAndFlush(hook);
}
if (changes.containsKey(configParamName)) {
final String configJson = command
.jsonFragment(configParamName);
final Set<HookConfiguration> config = assembleConfig(
command.mapValueOfParameterNamed(configJson),
template);
final boolean updated = hook.updateConfig(config);
if (!updated) {
changes.remove(configParamName);
}
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(hookId) //
.with(changes) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleHookDataIntegrityIssues(command, dve);
return null;
}
}
this.hookRepository.saveAndFlush(hook);
}
@Transactional
@Override
@CacheEvict(value = "hooks", allEntries = true)
public CommandProcessingResult deleteHook(final Long hookId) {
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(hookId) //
.with(changes) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleHookDataIntegrityIssues(command, dve);
return null;
}
}
this.context.authenticatedUser();
@Transactional
@Override
@CacheEvict(value = "hooks", allEntries = true)
public CommandProcessingResult deleteHook(final Long hookId) {
final Hook hook = retrieveHookBy(hookId);
this.context.authenticatedUser();
try {
this.hookRepository.delete(hook);
this.hookRepository.flush();
} catch (final DataIntegrityViolationException e) {
throw new PlatformDataIntegrityException(
"error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: "
+ e.getMostSpecificCause());
}
return new CommandProcessingResultBuilder().withEntityId(hookId)
.build();
}
final Hook hook = retrieveHookBy(hookId);
private Hook retrieveHookBy(final Long hookId) {
final Hook hook = this.hookRepository.findOne(hookId);
if (hook == null) {
throw new HookNotFoundException(hookId.toString());
}
return hook;
}
try {
this.hookRepository.delete(hook);
this.hookRepository.flush();
} catch (final DataIntegrityViolationException e) {
throw new PlatformDataIntegrityException(
"error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: "
+ e.getMostSpecificCause());
}
return new CommandProcessingResultBuilder().withEntityId(hookId)
.build();
}
private HookTemplate retrieveHookTemplateBy(final String templateName) {
final HookTemplate template = this.hookTemplateRepository
.findOne(templateName);
if (template == null) {
throw new HookTemplateNotFoundException(templateName);
}
return template;
}
private Hook retrieveHookBy(final Long hookId) {
final Hook hook = this.hookRepository.findOne(hookId);
if (hook == null) {
throw new HookNotFoundException(hookId.toString());
}
return hook;
}
private Set<HookConfiguration> assembleConfig(
final Map<String, String> hookConfig, final HookTemplate template) {
private HookTemplate retrieveHookTemplateBy(final String templateName) {
final HookTemplate template = this.hookTemplateRepository
.findOne(templateName);
if (template == null) {
throw new HookTemplateNotFoundException(templateName);
}
return template;
}
final Set<HookConfiguration> configuration = new HashSet<>();
final Set<Schema> fields = template.getSchema();
private Set<HookConfiguration> assembleConfig(
final Map<String, String> hookConfig, final HookTemplate template) {
for (final Entry<String, String> configEntry : hookConfig.entrySet()) {
for (final Schema field : fields) {
final String fieldName = field.getFieldName();
if (fieldName.equalsIgnoreCase(configEntry.getKey())) {
final Set<HookConfiguration> configuration = new HashSet<>();
final Set<Schema> fields = template.getSchema();
final HookConfiguration config = HookConfiguration
.createNewWithoutHook(field.getFieldType(),
configEntry.getKey(),
configEntry.getValue());
configuration.add(config);
break;
}
}
for (final Entry<String, String> configEntry : hookConfig.entrySet()) {
for (final Schema field : fields) {
final String fieldName = field.getFieldName();
if (fieldName.equalsIgnoreCase(configEntry.getKey())) {
}
final HookConfiguration config = HookConfiguration
.createNewWithoutHook(field.getFieldType(),
configEntry.getKey(),
configEntry.getValue());
configuration.add(config);
break;
}
}
return configuration;
}
}
private Set<HookResource> assembleSetOfEvents(final JsonArray eventsArray) {
return configuration;
}
final Set<HookResource> allEvents = new HashSet<>();
private Set<HookResource> assembleSetOfEvents(final JsonArray eventsArray) {
for (int i = 0; i < eventsArray.size(); i++) {
final Set<HookResource> allEvents = new HashSet<>();
final JsonObject eventElement = eventsArray.get(i)
.getAsJsonObject();
for (int i = 0; i < eventsArray.size(); i++) {
final String entityName = this.fromApiJsonHelper
.extractStringNamed(entityNameParamName, eventElement);
final String actionName = this.fromApiJsonHelper
.extractStringNamed(actionNameParamName, eventElement);
final HookResource event = HookResource.createNewWithoutHook(
entityName, actionName);
allEvents.add(event);
}
final JsonObject eventElement = eventsArray.get(i)
.getAsJsonObject();
return allEvents;
}
final String entityName = this.fromApiJsonHelper
.extractStringNamed(entityNameParamName, eventElement);
final String actionName = this.fromApiJsonHelper
.extractStringNamed(actionNameParamName, eventElement);
final HookResource event = HookResource.createNewWithoutHook(
entityName, actionName);
allEvents.add(event);
}
private void validateHookRules(final HookTemplate template,
final Set<HookConfiguration> config, Set<HookResource> events) {
return allEvents;
}
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("hook");
private void validateHookRules(final HookTemplate template,
final Set<HookConfiguration> config, Set<HookResource> events) {
if (!template.getName().equalsIgnoreCase(webTemplateName)
&& this.hookRepository.findOneByTemplateId(template.getId()) != null) {
final String errorMessage = "multiple.non.web.template.hooks.not.supported";
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("hook");
for (final HookConfiguration conf : config) {
final String fieldValue = conf.getFieldValue();
if (conf.getFieldName().equals(contentTypeName)) {
if (!(fieldValue.equalsIgnoreCase("json") || fieldValue
.equalsIgnoreCase("form"))) {
final String errorMessage = "content.type.must.be.json.or.form";
baseDataValidator.reset()
.failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
}
if (!template.getName().equalsIgnoreCase(webTemplateName)
&& this.hookRepository.findOneByTemplateId(template.getId()) != null) {
final String errorMessage = "multiple.non.web.template.hooks.not.supported";
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
if (conf.getFieldName().equals(payloadURLName)) {
try {
final WebHookService service = ProcessorHelper
.createWebHookService(fieldValue);
service.sendEmptyRequest();
} catch (RetrofitError re) {
// Swallow error if it's because of method not supported or
// if url throws 404 - required for integration test,
// url generated on 1st POST request
if (re.getResponse() == null) {
String errorMessage = "url.invalid";
baseDataValidator.reset()
.failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
}
}
}
for (final HookConfiguration conf : config) {
final String fieldValue = conf.getFieldValue();
if (conf.getFieldName().equals(contentTypeName)) {
if (!(fieldValue.equalsIgnoreCase("json") || fieldValue
.equalsIgnoreCase("form"))) {
final String errorMessage = "content.type.must.be.json.or.form";
baseDataValidator.reset()
.failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
}
if (events == null || events.isEmpty()) {
final String errorMessage = "registered.events.cannot.be.empty";
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
if (conf.getFieldName().equals(payloadURLName)) {
try {
final WebHookService service = ProcessorHelper
.createWebHookService(fieldValue);
service.sendEmptyRequest();
} catch (RetrofitError re) {
// Swallow error if it's because of method not supported or
// if url throws 404 - required for integration test,
// url generated on 1st POST request
if (re.getResponse() == null) {
String errorMessage = "url.invalid";
baseDataValidator.reset()
.failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
}
}
}
final Set<Schema> fields = template.getSchema();
for (final Schema field : fields) {
if (!field.isOptional()) {
boolean found = false;
for (final HookConfiguration conf : config) {
if (field.getFieldName().equals(conf.getFieldName())) {
found = true;
}
}
if (!found) {
final String errorMessage = "required.config.field."
+ "not.provided";
baseDataValidator.reset().value(field.getFieldName())
.failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
}
}
if (events == null || events.isEmpty()) {
final String errorMessage = "registered.events.cannot.be.empty";
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
final Set<Schema> fields = template.getSchema();
for (final Schema field : fields) {
if (!field.isOptional()) {
boolean found = false;
for (final HookConfiguration conf : config) {
if (field.getFieldName().equals(conf.getFieldName())) {
found = true;
}
}
if (!found) {
final String errorMessage = "required.config.field."
+ "not.provided";
baseDataValidator
.reset()
.value(field.getFieldName())
.failWithCodeNoParameterAddedToErrorCode(
errorMessage);
}
}
}
private void handleHookDataIntegrityIssues(final JsonCommand command,
final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("hook_name")) {
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException(
"error.msg.hook.duplicate.name", "A hook with name '"
+ name + "' already exists", "name", name);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
throw new PlatformDataIntegrityException(
"error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: "
+ realCause.getMessage());
}
private void handleHookDataIntegrityIssues(final JsonCommand command,
final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("hook_name")) {
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException(
"error.msg.hook.duplicate.name", "A hook with name '"
+ name + "' already exists", "name", name);
}
throw new PlatformDataIntegrityException(
"error.msg.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: "
+ realCause.getMessage());
}
}
@@ -28,7 +28,7 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@Entity
@Table(name = "m_template", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
@Table(name = "m_template", uniqueConstraints = {@UniqueConstraint(columnNames = {"name"}, name = "unq_name")})
public class Template extends AbstractPersistable<Long> {
@Column(name = "name", nullable = false, unique = true)
@@ -49,7 +49,8 @@ public class Template extends AbstractPersistable<Long> {
@OneToMany(targetEntity = TemplateMapper.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<TemplateMapper> mappers;
public Template(final String name, final String text, final TemplateEntity entity, final TemplateType type,
public Template(final String name, final String text,
final TemplateEntity entity, final TemplateType type,
final List<TemplateMapper> mappers) {
this.name = StringUtils.defaultIfEmpty(name, null);
this.entity = entity;
@@ -65,16 +66,29 @@ public class Template extends AbstractPersistable<Long> {
public static Template fromJson(final JsonCommand command) {
final String name = command.stringValueOfParameterNamed("name");
final String text = command.stringValueOfParameterNamed("text");
final TemplateEntity entity = TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed("entity")];
final TemplateType type = TemplateType.values()[command.integerValueSansLocaleOfParameterNamed("type")];
final TemplateEntity entity = TemplateEntity.values()[command
.integerValueSansLocaleOfParameterNamed("entity")];
final int templateTypeId = command
.integerValueSansLocaleOfParameterNamed("type");
TemplateType type = null;
switch (templateTypeId) {
case 0 :
type = TemplateType.DOCUMENT;
break;
case 2 :
type = TemplateType.SMS;
break;
}
final JsonArray array = command.arrayOfParameterNamed("mappers");
final List<TemplateMapper> mappersList = new ArrayList<>();
for (final JsonElement element : array) {
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString()));
mappersList.add(new TemplateMapper(element.getAsJsonObject()
.get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject()
.get("mappersvalue").getAsString()));
}
return new Template(name, text, entity, type, mappersList);
@@ -13,11 +13,11 @@ import com.google.gson.annotations.SerializedName;
public enum TemplateType {
@SerializedName("Document")
DOCUMENT(0, "Document");
DOCUMENT(0, "Document"), @SerializedName("SMS")
SMS(2, "SMS");
/**
* @SerializedName("E-Mail") EMAIL(1, "E-Mail"),
* @SerializedName("SMS") SMS(2, "SMS");
* @SerializedName("E-Mail") EMAIL(1, "E-Mail")
*/
private int id;
private String name;
@@ -44,7 +44,9 @@ public class JpaTemplateDomainService implements TemplateDomainService {
@Override
public Template findOneById(final Long id) {
final Template template = this.templateRepository.findOne(id);
if (template == null) { throw new TemplateNotFoundException(id); }
if (template == null) {
throw new TemplateNotFoundException(id);
}
return template;
}
@@ -58,12 +60,14 @@ public class JpaTemplateDomainService implements TemplateDomainService {
final Template template = Template.fromJson(command);
this.templateRepository.saveAndFlush(template);
return new CommandProcessingResultBuilder().withEntityId(template.getId()).build();
return new CommandProcessingResultBuilder().withEntityId(
template.getId()).build();
}
@Transactional
@Override
public CommandProcessingResult updateTemplate(final Long templateId, final JsonCommand command) {
public CommandProcessingResult updateTemplate(final Long templateId,
final JsonCommand command) {
// FIXME - no validation here of the data in the command object, is
// name, text populated etc
// FIXME - handle cases where data integrity constraints are fired from
@@ -72,20 +76,36 @@ public class JpaTemplateDomainService implements TemplateDomainService {
final Template template = findOneById(templateId);
template.setName(command.stringValueOfParameterNamed(PROPERTY_NAME));
template.setText(command.stringValueOfParameterNamed(PROPERTY_TEXT));
template.setEntity(TemplateEntity.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_ENTITY)]);
template.setType(TemplateType.values()[command.integerValueSansLocaleOfParameterNamed(PROPERTY_TYPE)]);
template.setEntity(TemplateEntity.values()[command
.integerValueSansLocaleOfParameterNamed(PROPERTY_ENTITY)]);
final int templateTypeId = command
.integerValueSansLocaleOfParameterNamed(PROPERTY_TYPE);
TemplateType type = null;
switch (templateTypeId) {
case 0 :
type = TemplateType.DOCUMENT;
break;
case 2 :
type = TemplateType.SMS;
break;
}
template.setType(type);
final JsonArray array = command.arrayOfParameterNamed("mappers");
final List<TemplateMapper> mappersList = new ArrayList<>();
for (final JsonElement element : array) {
mappersList.add(new TemplateMapper(element.getAsJsonObject().get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject().get("mappersvalue").getAsString()));
mappersList.add(new TemplateMapper(element.getAsJsonObject()
.get("mappersorder").getAsInt(), element.getAsJsonObject()
.get("mapperskey").getAsString(), element.getAsJsonObject()
.get("mappersvalue").getAsString()));
}
template.setMappers(mappersList);
this.templateRepository.saveAndFlush(template);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(template.getId()).build();
return new CommandProcessingResultBuilder()
.withCommandId(command.commandId())
.withEntityId(template.getId()).build();
}
@Transactional
@@ -95,7 +115,8 @@ public class JpaTemplateDomainService implements TemplateDomainService {
this.templateRepository.delete(template);
return new CommandProcessingResultBuilder().withEntityId(templateId).build();
return new CommandProcessingResultBuilder().withEntityId(templateId)
.build();
}
@Transactional
@@ -105,7 +126,8 @@ public class JpaTemplateDomainService implements TemplateDomainService {
}
@Override
public List<Template> getAllByEntityAndType(final TemplateEntity entity, final TemplateType type) {
public List<Template> getAllByEntityAndType(final TemplateEntity entity,
final TemplateType type) {
return this.templateRepository.findByEntityAndType(entity, type);
}
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper;
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
import org.mifosplatform.template.domain.Template;
import org.mifosplatform.template.domain.TemplateFunctions;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -35,23 +36,32 @@ import com.github.mustachejava.MustacheFactory;
@Service
public class TemplateMergeService {
// private final FromJsonHelper fromApiJsonHelper;
// private final FromJsonHelper fromApiJsonHelper;
private Map<String, Object> scopes;
private String authToken;
// @Autowired
// public TemplateMergeService(final FromJsonHelper fromApiJsonHelper) {
// this.fromApiJsonHelper = fromApiJsonHelper;
// }
// @Autowired
// public TemplateMergeService(final FromJsonHelper fromApiJsonHelper) {
// this.fromApiJsonHelper = fromApiJsonHelper;
// }
public String compile(final Template template, final Map<String, Object> scopes) throws MalformedURLException, IOException {
public void setAuthToken(final String authToken) {
this.authToken = authToken;
}
public String compile(final Template template,
final Map<String, Object> scopes) throws MalformedURLException,
IOException {
this.scopes = scopes;
this.scopes.put("static", new TemplateFunctions());
final MustacheFactory mf = new DefaultMustacheFactory();
final Mustache mustache = mf.compile(new StringReader(template.getText()), template.getName());
final Mustache mustache = mf.compile(
new StringReader(template.getText()), template.getName());
final Map<String, Object> mappers = getCompiledMapFromMappers(template.getMappersAsMap());
final Map<String, Object> mappers = getCompiledMapFromMappers(template
.getMappersAsMap());
this.scopes.putAll(mappers);
final StringWriter stringWriter = new StringWriter();
@@ -60,14 +70,16 @@ public class TemplateMergeService {
return stringWriter.toString();
}
private Map<String, Object> getCompiledMapFromMappers(final Map<String, String> data) {
private Map<String, Object> getCompiledMapFromMappers(
final Map<String, String> data) {
final MustacheFactory mf = new DefaultMustacheFactory();
if (data != null) {
for (final Map.Entry<String, String> entry : data.entrySet()) {
final Mustache mappersMustache = mf.compile(new StringReader(entry.getValue()), "");
final Mustache mappersMustache = mf.compile(new StringReader(
entry.getValue()), "");
final StringWriter stringWriter = new StringWriter();
mappersMustache.execute(stringWriter, this.scopes);
@@ -88,11 +100,13 @@ public class TemplateMergeService {
}
@SuppressWarnings("unchecked")
private Map<String, Object> getMapFromUrl(final String url) throws MalformedURLException, IOException {
private Map<String, Object> getMapFromUrl(final String url)
throws MalformedURLException, IOException {
final HttpURLConnection connection = getConnection(url);
final String response = getStringFromInputStream(connection.getInputStream());
final String response = getStringFromInputStream(connection
.getInputStream());
HashMap<String, Object> result = new HashMap<>();
if (connection.getContentType().equals("text/plain")) {
result.put("src", response);
@@ -104,20 +118,29 @@ public class TemplateMergeService {
private HttpURLConnection getConnection(final String url) {
final String name = SecurityContextHolder.getContext().getAuthentication().getName();
final String password = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
if (this.authToken == null) {
final String name = SecurityContextHolder.getContext()
.getAuthentication().getName();
final String password = SecurityContextHolder.getContext()
.getAuthentication().getCredentials().toString();
Authenticator.setDefault(new Authenticator() {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(name, password.toCharArray());
}
});
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(name, password
.toCharArray());
}
});
}
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
if (this.authToken != null) {
connection.setRequestProperty("Authorization", "Basic "
+ this.authToken);
}
TrustModifier.relaxHostChecking(connection);
connection.setDoInput(true);
@@ -0,0 +1,2 @@
ALTER TABLE `m_hook` ADD COLUMN `ugd_template_id` bigint(20) NOT NULL;
ALTER TABLE `m_hook` ADD CONSTRAINT `fk_ugd_template_id` FOREIGN KEY (`ugd_template_id`) REFERENCES `m_template` (`id`);