Browse Source

Add default subject to notification template, add 'enabled' option; refactoring

pull/7980/head
ViacheslavKlimov 4 years ago
parent
commit
6eea14bcf7
  1. 33
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
  2. 43
      application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java
  3. 7
      application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java
  4. 5
      application/src/main/java/org/thingsboard/server/service/notification/channels/NotificationChannel.java
  5. 8
      application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java
  6. 11
      application/src/main/java/org/thingsboard/server/service/notification/channels/SmsNotificationChannel.java
  7. 2
      application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java
  8. 7
      application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java
  9. 5
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java
  10. 12
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java
  11. 17
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java
  12. 24
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/HasSubject.java
  13. 18
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java
  14. 16
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/PushDeliveryMethodNotificationTemplate.java
  15. 13
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SlackDeliveryMethodNotificationTemplate.java
  16. 11
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SmsDeliveryMethodNotificationTemplate.java
  17. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java

33
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java

@ -23,7 +23,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.common.util.DonAsynchron; import org.thingsboard.common.util.DonAsynchron;
import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.rule.engine.api.NotificationCenter;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
@ -76,8 +75,8 @@ import java.util.stream.Collectors;
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@SuppressWarnings("UnstableApiUsage") @SuppressWarnings({"UnstableApiUsage", "rawtypes"})
public class DefaultNotificationCenter extends AbstractSubscriptionService implements NotificationCenter, NotificationChannel { public class DefaultNotificationCenter extends AbstractSubscriptionService implements NotificationCenter, NotificationChannel<PushDeliveryMethodNotificationTemplate> {
private final NotificationTargetService notificationTargetService; private final NotificationTargetService notificationTargetService;
private final NotificationRequestService notificationRequestService; private final NotificationRequestService notificationRequestService;
@ -97,7 +96,8 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
NotificationSettings settings = notificationSettingsService.findNotificationSettings(tenantId); NotificationSettings settings = notificationSettingsService.findNotificationSettings(tenantId);
NotificationTemplate notificationTemplate = notificationTemplateService.findNotificationTemplateById(tenantId, notificationRequest.getTemplateId()); NotificationTemplate notificationTemplate = notificationTemplateService.findNotificationTemplateById(tenantId, notificationRequest.getTemplateId());
notificationTemplate.getConfiguration().getDeliveryMethodsTemplates().keySet().forEach(deliveryMethod -> { notificationTemplate.getConfiguration().getDeliveryMethodsTemplates().forEach((deliveryMethod, template) -> {
if (!template.isEnabled()) return;
if (settings.getDeliveryMethodsConfigs().containsKey(deliveryMethod) && if (settings.getDeliveryMethodsConfigs().containsKey(deliveryMethod) &&
!settings.getDeliveryMethodsConfigs().get(deliveryMethod).isEnabled()) { !settings.getDeliveryMethodsConfigs().get(deliveryMethod).isEnabled()) {
throw new IllegalArgumentException("Delivery method " + deliveryMethod + " is disabled"); throw new IllegalArgumentException("Delivery method " + deliveryMethod + " is disabled");
@ -182,14 +182,13 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
if (ctx.getStats().contains(deliveryMethod, recipient.getId())) { if (ctx.getStats().contains(deliveryMethod, recipient.getId())) {
return Futures.immediateFailedFuture(new AlreadySentException()); return Futures.immediateFailedFuture(new AlreadySentException());
} }
String text; DeliveryMethodNotificationTemplate processedTemplate;
try { try {
DeliveryMethodNotificationTemplate template = ctx.getTemplate(deliveryMethod); processedTemplate = ctx.getProcessedTemplate(deliveryMethod, recipient);
text = TbNodeUtils.processTemplate(template.getBody(), ctx.createTemplateContext(recipient));
} catch (Exception e) { } catch (Exception e) {
return Futures.immediateFailedFuture(e); return Futures.immediateFailedFuture(e);
} }
return notificationChannel.sendNotification(recipient, text, ctx); return notificationChannel.sendNotification(recipient, processedTemplate, ctx);
} }
private void forwardToNotificationSchedulerService(TenantId tenantId, NotificationRequestId notificationRequestId) { private void forwardToNotificationSchedulerService(TenantId tenantId, NotificationRequestId notificationRequestId) {
@ -206,16 +205,15 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
} }
@Override @Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) { public ListenableFuture<Void> sendNotification(User recipient, PushDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) {
PushDeliveryMethodNotificationTemplate template = ctx.getTemplate(NotificationDeliveryMethod.PUSH);
NotificationRequest request = ctx.getRequest(); NotificationRequest request = ctx.getRequest();
log.trace("Creating notification for recipient {} (notification request id: {})", recipient.getId(), request.getId()); log.trace("Creating notification for recipient {} (notification request id: {})", recipient.getId(), request.getId());
Notification notification = Notification.builder() Notification notification = Notification.builder()
.requestId(request.getId()) .requestId(request.getId())
.recipientId(recipient.getId()) .recipientId(recipient.getId())
.type(ctx.getNotificationTemplate().getNotificationType()) .type(ctx.getNotificationTemplate().getNotificationType())
.subject(template.getSubject()) .subject(processedTemplate.getSubject())
.text(text) .text(processedTemplate.getBody())
.info(request.getInfo()) .info(request.getInfo())
.status(NotificationStatus.SENT) .status(NotificationStatus.SENT)
.build(); .build();
@ -281,11 +279,14 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
@Override @Override
public void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId) { public void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId) {
log.debug("Deleting notification request {}", notificationRequestId); log.debug("Deleting notification request {}", notificationRequestId);
NotificationRequest notificationRequest = notificationRequestService.findNotificationRequestById(tenantId, notificationRequestId);// TODO: add caching
notificationRequestService.deleteNotificationRequestById(tenantId, notificationRequestId); notificationRequestService.deleteNotificationRequestById(tenantId, notificationRequestId);
onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder() if (notificationRequest.isSent()) {
.notificationRequestId(notificationRequestId) onNotificationRequestUpdate(tenantId, NotificationRequestUpdate.builder()
.deleted(true) .notificationRequestId(notificationRequestId)
.build()); .deleted(true)
.build());
}
clusterService.broadcastEntityStateChangeEvent(tenantId, notificationRequestId, ComponentLifecycleEvent.DELETED); clusterService.broadcastEntityStateChangeEvent(tenantId, notificationRequestId, ComponentLifecycleEvent.DELETED);
} }

43
application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java

@ -19,20 +19,22 @@ import com.google.common.base.Strings;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.info.AlarmOriginatedNotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStats; import org.thingsboard.server.common.data.notification.NotificationRequestStats;
import org.thingsboard.server.common.data.notification.info.RuleNodeOriginatedNotificationInfo; import org.thingsboard.server.common.data.notification.info.AlarmOriginatedNotificationInfo;
import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.HasSubject;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig; import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -48,7 +50,7 @@ public class NotificationProcessingContext {
@Getter @Getter
private final NotificationTemplate notificationTemplate; private final NotificationTemplate notificationTemplate;
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates; private final Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates;
@Getter @Getter
private Set<NotificationDeliveryMethod> deliveryMethods; private Set<NotificationDeliveryMethod> deliveryMethods;
@Getter @Getter
@ -61,29 +63,50 @@ public class NotificationProcessingContext {
this.request = request; this.request = request;
this.settings = settings; this.settings = settings;
this.notificationTemplate = template; this.notificationTemplate = template;
this.templates = new EnumMap<>(NotificationDeliveryMethod.class);
this.stats = new NotificationRequestStats(); this.stats = new NotificationRequestStats();
} }
public void init() { public void init() {
NotificationTemplateConfig templateConfig = notificationTemplate.getConfiguration(); NotificationTemplateConfig templateConfig = notificationTemplate.getConfiguration();
templates = templateConfig.getDeliveryMethodsTemplates(); templateConfig.getDeliveryMethodsTemplates().forEach((deliveryMethod, template) -> {
templates.forEach((deliveryMethod, template) -> { if (!template.isEnabled()) return;
template = template.copy();
if (StringUtils.isEmpty(template.getBody())) { if (StringUtils.isEmpty(template.getBody())) {
template.setBody(templateConfig.getDefaultTextTemplate()); template.setBody(templateConfig.getDefaultTextTemplate());
} }
if (template instanceof HasSubject) {
if (StringUtils.isEmpty(((HasSubject) template).getSubject())) {
((HasSubject) template).setSubject(templateConfig.getNotificationSubject());
}
}
templates.put(deliveryMethod, template);
}); });
deliveryMethods = templates.keySet(); deliveryMethods = templates.keySet();
} }
public <T extends DeliveryMethodNotificationTemplate> T getTemplate(NotificationDeliveryMethod deliveryMethod) {
return (T) templates.get(deliveryMethod);
}
public <C extends NotificationDeliveryMethodConfig> C getDeliveryMethodConfig(NotificationDeliveryMethod deliveryMethod) { public <C extends NotificationDeliveryMethodConfig> C getDeliveryMethodConfig(NotificationDeliveryMethod deliveryMethod) {
return (C) settings.getDeliveryMethodsConfigs().get(deliveryMethod); return (C) settings.getDeliveryMethodsConfigs().get(deliveryMethod);
} }
public Map<String, String> createTemplateContext(User recipient) { protected <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, User recipient) {
Map<String, String> templateContext = createTemplateContext(recipient);
T template = (T) templates.get(deliveryMethod).copy();
template.setBody(processTemplate(template.getBody(), templateContext));
if (template instanceof HasSubject) {
String subject = ((HasSubject) template).getSubject();
((HasSubject) template).setSubject(processTemplate(subject, templateContext));
}
return template;
}
private <T extends DeliveryMethodNotificationTemplate> String processTemplate(String template, Map<String, String> context) {
return TbNodeUtils.processTemplate(template, context);
}
private Map<String, String> createTemplateContext(User recipient) {
Map<String, String> templateContext = new HashMap<>(); Map<String, String> templateContext = new HashMap<>();
templateContext.put("email", recipient.getEmail()); templateContext.put("email", recipient.getEmail());
templateContext.put("firstName", Strings.nullToEmpty(recipient.getFirstName())); templateContext.put("firstName", Strings.nullToEmpty(recipient.getFirstName()));

7
application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java

@ -27,16 +27,15 @@ import org.thingsboard.server.service.notification.NotificationProcessingContext
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class EmailNotificationChannel implements NotificationChannel { public class EmailNotificationChannel implements NotificationChannel<EmailDeliveryMethodNotificationTemplate> {
private final MailService mailService; private final MailService mailService;
private final MailExecutorService executor; private final MailExecutorService executor;
@Override @Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) { public ListenableFuture<Void> sendNotification(User recipient, EmailDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) {
EmailDeliveryMethodNotificationTemplate template = ctx.getTemplate(NotificationDeliveryMethod.EMAIL);
return executor.submit(() -> { return executor.submit(() -> {
mailService.sendEmail(recipient.getTenantId(), recipient.getEmail(), template.getSubject(), text); mailService.sendEmail(recipient.getTenantId(), recipient.getEmail(), processedTemplate.getSubject(), processedTemplate.getBody());
return null; return null;
}); });
} }

5
application/src/main/java/org/thingsboard/server/service/notification/channels/NotificationChannel.java

@ -18,11 +18,12 @@ package org.thingsboard.server.service.notification.channels;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
import org.thingsboard.server.service.notification.NotificationProcessingContext; import org.thingsboard.server.service.notification.NotificationProcessingContext;
public interface NotificationChannel { public interface NotificationChannel<T extends DeliveryMethodNotificationTemplate> {
ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx); ListenableFuture<Void> sendNotification(User recipient, T processedTemplate, NotificationProcessingContext ctx);
NotificationDeliveryMethod getDeliveryMethod(); NotificationDeliveryMethod getDeliveryMethod();

8
application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java

@ -30,22 +30,20 @@ import org.thingsboard.server.service.notification.NotificationProcessingContext
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class SlackNotificationChannel implements NotificationChannel { public class SlackNotificationChannel implements NotificationChannel<SlackDeliveryMethodNotificationTemplate> {
private final SlackService slackService; private final SlackService slackService;
private final ExternalCallExecutorService executor; private final ExternalCallExecutorService executor;
@Override @Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) { public ListenableFuture<Void> sendNotification(User recipient, SlackDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) {
if (ctx.getStats().contains(NotificationDeliveryMethod.SLACK)) { if (ctx.getStats().contains(NotificationDeliveryMethod.SLACK)) {
return Futures.immediateFailedFuture(new AlreadySentException()); return Futures.immediateFailedFuture(new AlreadySentException());
} }
SlackDeliveryMethodNotificationTemplate template = ctx.getTemplate(NotificationDeliveryMethod.SLACK);
SlackNotificationDeliveryMethodConfig config = ctx.getDeliveryMethodConfig(NotificationDeliveryMethod.SLACK); SlackNotificationDeliveryMethodConfig config = ctx.getDeliveryMethodConfig(NotificationDeliveryMethod.SLACK);
return executor.submit(() -> { return executor.submit(() -> {
slackService.sendMessage(ctx.getTenantId(), config.getBotToken(), template.getConversationId(), text); slackService.sendMessage(ctx.getTenantId(), config.getBotToken(), processedTemplate.getConversationId(), processedTemplate.getBody());
return null; return null;
}); });
} }

11
application/src/main/java/org/thingsboard/server/service/notification/channels/SmsNotificationChannel.java

@ -23,22 +23,25 @@ import org.springframework.stereotype.Component;
import org.thingsboard.rule.engine.api.SmsService; import org.thingsboard.rule.engine.api.SmsService;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.template.SmsDeliveryMethodNotificationTemplate;
import org.thingsboard.server.service.notification.NotificationProcessingContext; import org.thingsboard.server.service.notification.NotificationProcessingContext;
import org.thingsboard.server.service.sms.SmsExecutorService; import org.thingsboard.server.service.sms.SmsExecutorService;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class SmsNotificationChannel implements NotificationChannel { public class SmsNotificationChannel implements NotificationChannel<SmsDeliveryMethodNotificationTemplate> {
private final SmsService smsService; private final SmsService smsService;
private final SmsExecutorService executor; private final SmsExecutorService executor;
@Override @Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) { public ListenableFuture<Void> sendNotification(User recipient, SmsDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) {
String phone = recipient.getPhone(); String phone = recipient.getPhone();
if (StringUtils.isBlank(phone)) return Futures.immediateFailedFuture(new RuntimeException("User does not have phone number")); if (StringUtils.isBlank(phone))
return Futures.immediateFailedFuture(new RuntimeException("User does not have phone number"));
return executor.submit(() -> { return executor.submit(() -> {
smsService.sendSms(recipient.getTenantId(), recipient.getCustomerId(), new String[]{phone}, text); smsService.sendSms(recipient.getTenantId(), recipient.getCustomerId(), new String[]{phone}, processedTemplate.getBody());
return null; return null;
}); });
} }

2
application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java

@ -28,7 +28,6 @@ import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestConfig; import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.NotificationType;
@ -140,6 +139,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
default: default:
throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod); throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod);
} }
deliveryMethodNotificationTemplate.setEnabled(true);
config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate); config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate);
} }
notificationTemplate.setConfiguration(config); notificationTemplate.setConfiguration(config);

7
application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java

@ -56,7 +56,9 @@ public class NotificationTemplateApiTest extends AbstractControllerTest {
NotificationTemplateConfig config = new NotificationTemplateConfig(); NotificationTemplateConfig config = new NotificationTemplateConfig();
notificationTemplate.setConfiguration(config); notificationTemplate.setConfiguration(config);
config.setDefaultTextTemplate("Default text"); config.setDefaultTextTemplate("Default text");
config.setNotificationSubject(null);
EmailDeliveryMethodNotificationTemplate emailTemplate = new EmailDeliveryMethodNotificationTemplate(); EmailDeliveryMethodNotificationTemplate emailTemplate = new EmailDeliveryMethodNotificationTemplate();
emailTemplate.setEnabled(true);
emailTemplate.setBody(null); emailTemplate.setBody(null);
emailTemplate.setSubject(null); emailTemplate.setSubject(null);
config.setDeliveryMethodsTemplates(Map.of( config.setDeliveryMethodsTemplates(Map.of(
@ -66,15 +68,14 @@ public class NotificationTemplateApiTest extends AbstractControllerTest {
validationError = saveAndGetError(notificationTemplate, status().isBadRequest()); validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
assertThat(validationError) assertThat(validationError)
.doesNotContain("defaultTextTemplate must be specified") .contains("notificationSubject must be")
.contains("subject must not be")
.contains("name is malformed"); .contains("name is malformed");
config.setDefaultTextTemplate(null); config.setDefaultTextTemplate(null);
validationError = saveAndGetError(notificationTemplate, status().isBadRequest()); validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
assertThat(validationError) assertThat(validationError)
.contains("defaultTextTemplate must be specified"); .contains("defaultTextTemplate").contains("must be specified");
} }
private String saveAndGetError(NotificationTemplate notificationTemplate, ResultMatcher statusMatcher) throws Exception { private String saveAndGetError(NotificationTemplate notificationTemplate, ResultMatcher statusMatcher) throws Exception {

5
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java

@ -75,4 +75,9 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
return originatorEntityId instanceof UserId ? (UserId) originatorEntityId : null; return originatorEntityId instanceof UserId ? (UserId) originatorEntityId : null;
} }
@JsonIgnore
public boolean isSent() {
return status == NotificationRequestStatus.SENT;
}
} }

12
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java

@ -15,11 +15,13 @@
*/ */
package org.thingsboard.server.common.data.notification.template; package org.thingsboard.server.common.data.notification.template;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
@ -31,10 +33,20 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho
@Type(name = "SLACK", value = SlackDeliveryMethodNotificationTemplate.class) @Type(name = "SLACK", value = SlackDeliveryMethodNotificationTemplate.class)
}) })
@Data @Data
@NoArgsConstructor
public abstract class DeliveryMethodNotificationTemplate { public abstract class DeliveryMethodNotificationTemplate {
private boolean enabled;
private String body; private String body;
public DeliveryMethodNotificationTemplate(DeliveryMethodNotificationTemplate other) {
this.enabled = other.enabled;
this.body = other.body;
}
public abstract NotificationDeliveryMethod getMethod(); public abstract NotificationDeliveryMethod getMethod();
@JsonIgnore
public abstract DeliveryMethodNotificationTemplate copy();
} }

17
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java

@ -17,20 +17,29 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import javax.validation.constraints.NotBlank;
@Data @Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class EmailDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate { public class EmailDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate implements HasSubject {
@NotBlank
private String subject; private String subject;
public EmailDeliveryMethodNotificationTemplate(EmailDeliveryMethodNotificationTemplate other) {
super(other);
this.subject = other.subject;
}
@Override @Override
public NotificationDeliveryMethod getMethod() { public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.EMAIL; return NotificationDeliveryMethod.EMAIL;
} }
@Override
public EmailDeliveryMethodNotificationTemplate copy() {
return new EmailDeliveryMethodNotificationTemplate(this);
}
} }

24
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/HasSubject.java

@ -0,0 +1,24 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed 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.thingsboard.server.common.data.notification.template;
public interface HasSubject {
String getSubject();
void setSubject(String subject);
}

18
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java

@ -28,19 +28,27 @@ import java.util.Map;
@Data @Data
public class NotificationTemplateConfig { public class NotificationTemplateConfig {
private String notificationSubject;
private String defaultTextTemplate; private String defaultTextTemplate;
@Valid @Valid
@NotEmpty @NotEmpty
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> deliveryMethodsTemplates; private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> deliveryMethodsTemplates;
@JsonIgnore @JsonIgnore
@AssertTrue(message = "defaultTextTemplate must be specified if one absent for delivery method") @AssertTrue(message = "defaultTextTemplate and notificationSubject must be specified if one absent for delivery method")
public boolean isValid() { public boolean isValid() {
if (deliveryMethodsTemplates.values().stream().anyMatch(template -> StringUtils.isEmpty(template.getBody()))) { for (DeliveryMethodNotificationTemplate template : deliveryMethodsTemplates.values()) {
return StringUtils.isNotEmpty(defaultTextTemplate); if (StringUtils.isEmpty(template.getBody()) && StringUtils.isEmpty(defaultTextTemplate)) {
} else { return false;
return true; }
if (template instanceof HasSubject) {
String subject = ((HasSubject) template).getSubject();
if (StringUtils.isEmpty(subject) && StringUtils.isEmpty(notificationSubject)) {
return false;
}
}
} }
return true;
} }
} }

16
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/PushDeliveryMethodNotificationTemplate.java

@ -17,19 +17,33 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data @Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class PushDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate { public class PushDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate implements HasSubject {
private String subject; private String subject;
private String icon; private String icon;
private String actionButtonConfig; private String actionButtonConfig;
public PushDeliveryMethodNotificationTemplate(PushDeliveryMethodNotificationTemplate other) {
super(other);
this.subject = other.subject;
this.icon = other.icon;
this.actionButtonConfig = other.actionButtonConfig;
}
@Override @Override
public NotificationDeliveryMethod getMethod() { public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.PUSH; return NotificationDeliveryMethod.PUSH;
} }
@Override
public PushDeliveryMethodNotificationTemplate copy() {
return new PushDeliveryMethodNotificationTemplate(this);
}
} }

13
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SlackDeliveryMethodNotificationTemplate.java

@ -17,11 +17,13 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
@Data @Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate { public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
@ -29,9 +31,20 @@ public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotif
@NotEmpty @NotEmpty
private String conversationId; private String conversationId;
public SlackDeliveryMethodNotificationTemplate(SlackDeliveryMethodNotificationTemplate other) {
super(other);
this.conversationType = other.conversationType;
this.conversationId = other.conversationId;
}
@Override @Override
public NotificationDeliveryMethod getMethod() { public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.SLACK; return NotificationDeliveryMethod.SLACK;
} }
@Override
public SlackDeliveryMethodNotificationTemplate copy() {
return new SlackDeliveryMethodNotificationTemplate(this);
}
} }

11
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SmsDeliveryMethodNotificationTemplate.java

@ -17,15 +17,26 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data @Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class SmsDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate { public class SmsDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
public SmsDeliveryMethodNotificationTemplate(SmsDeliveryMethodNotificationTemplate other) {
super(other);
}
@Override @Override
public NotificationDeliveryMethod getMethod() { public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.SMS; return NotificationDeliveryMethod.SMS;
} }
@Override
public DeliveryMethodNotificationTemplate copy() {
return new SmsDeliveryMethodNotificationTemplate(this);
}
} }

2
dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java

@ -94,7 +94,7 @@ public class EntityKeyMapping {
allowedEntityFieldMap.get(EntityType.TENANT).add(REGION); allowedEntityFieldMap.get(EntityType.TENANT).add(REGION);
allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields)); allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields));
allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL, ADDITIONAL_INFO))); allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL, PHONE, ADDITIONAL_INFO)));
allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(dashboardEntityFields)); allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(dashboardEntityFields));
allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields)); allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields));

Loading…
Cancel
Save