Browse Source

Move delivery methods to notification template; refactoring

pull/7980/head
ViacheslavKlimov 4 years ago
parent
commit
38c9d5dcd8
  1. 2
      application/src/main/data/upgrade/3.4.3/schema_update.sql
  2. 20
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
  3. 2
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java
  4. 3
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java
  5. 11
      application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java
  6. 11
      application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java
  7. 34
      application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java
  8. 38
      application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java
  9. 5
      application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java
  10. 5
      application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java
  11. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java
  12. 5
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java
  13. 9
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java
  14. 15
      common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/AccountNotificationSettings.java
  15. 17
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java
  16. 9
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java
  17. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java
  18. 5
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java
  19. 35
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/PushDeliveryMethodNotificationTemplate.java
  20. 11
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SlackDeliveryMethodNotificationTemplate.java
  21. 31
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SmsDeliveryMethodNotificationTemplate.java
  22. 3
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  23. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java
  24. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java
  25. 2
      dao/src/main/resources/sql/schema-entities.sql
  26. 3
      rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NotificationCenter.java
  27. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java
  28. 4
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java

2
application/src/main/data/upgrade/3.4.3/schema_update.sql

@ -29,7 +29,6 @@ CREATE TABLE IF NOT EXISTS notification_template (
tenant_id UUID NULL CONSTRAINT fk_notification_template_tenant_id REFERENCES tenant(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
notification_type VARCHAR(32) NOT NULL,
notification_subject VARCHAR(255),
configuration VARCHAR(10000) NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_notification_template_tenant_id_created_time ON notification_template(tenant_id, created_time DESC);
@ -52,7 +51,6 @@ CREATE TABLE IF NOT EXISTS notification_request (
targets VARCHAR(10000) NOT NULL,
template_id UUID NOT NULL,
info VARCHAR(1000),
delivery_methods VARCHAR(255),
additional_config VARCHAR(1000),
originator_type VARCHAR(32) NOT NULL,
originator_entity_id UUID,

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

@ -43,6 +43,7 @@ import org.thingsboard.server.common.data.notification.NotificationType;
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.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.PushDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;
@ -97,7 +98,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
NotificationSettings settings = notificationSettingsService.findNotificationSettings(tenantId);
NotificationTemplate notificationTemplate = notificationTemplateService.findNotificationTemplateById(tenantId, notificationRequest.getTemplateId());
notificationRequest.getDeliveryMethods().forEach(deliveryMethod -> {
notificationTemplate.getConfiguration().getDeliveryMethodsTemplates().keySet().forEach(deliveryMethod -> {
if (settings.getDeliveryMethodsConfigs().containsKey(deliveryMethod) &&
!settings.getDeliveryMethodsConfigs().get(deliveryMethod).isEnabled()) {
throw new IllegalArgumentException("Delivery method " + deliveryMethod + " is disabled");
@ -106,10 +107,6 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
if (!settings.getDeliveryMethodsConfigs().containsKey(deliveryMethod)) {
throw new IllegalArgumentException("Slack must be configured in the settings");
}
if (!notificationTemplate.getConfiguration().getTemplates().containsKey(deliveryMethod)) {
throw new IllegalArgumentException("To send notification via Slack, " +
"you need to configure corresponding template");
}
}
});
@ -139,7 +136,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
DaoUtil.processBatches(pageLink -> {
return notificationTargetService.findRecipientsForNotificationTarget(tenantId, ctx.getCustomerId(), targetId, pageLink);
}, 200, recipientsBatch -> {
for (NotificationDeliveryMethod deliveryMethod : savedNotificationRequest.getDeliveryMethods()) {
for (NotificationDeliveryMethod deliveryMethod : ctx.getDeliveryMethods()) {
List<User> recipients = recipientsBatch.getData();
log.debug("Sending {} notifications for request {} to recipients batch ({})", deliveryMethod, savedNotificationRequest.getId(), recipients.size());
NotificationChannel notificationChannel = channels.get(deliveryMethod);
@ -168,11 +165,11 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
if (senderId != null) {
if (stats.getErrors().isEmpty()) {
int sent = stats.getSent().values().stream().mapToInt(AtomicInteger::get).sum();
sendBasicNotification(tenantId, senderId, NotificationType.COMPLETED, "Notifications sent",
sendBasicNotification(tenantId, senderId, "Notifications sent",
"All notifications were successfully sent (" + sent + ")");
} else {
int failures = stats.getErrors().values().stream().mapToInt(Map::size).sum();
sendBasicNotification(tenantId, senderId, NotificationType.FAILURE, "Notification failure",
sendBasicNotification(tenantId, senderId, "Notification failure",
"Some notifications were not sent (" + failures + ")"); // TODO: 'Go to request' button
}
}
@ -211,13 +208,14 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
@Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) {
PushDeliveryMethodNotificationTemplate template = ctx.getTemplate(NotificationDeliveryMethod.PUSH);
NotificationRequest request = ctx.getRequest();
log.trace("Creating notification for recipient {} (notification request id: {})", recipient.getId(), request.getId());
Notification notification = Notification.builder()
.requestId(request.getId())
.recipientId(recipient.getId())
.type(ctx.getNotificationTemplate().getNotificationType())
.subject(ctx.getNotificationTemplate().getNotificationSubject())
.subject(template.getSubject())
.text(text)
.info(request.getInfo())
.originatorType(request.getOriginatorType())
@ -238,10 +236,10 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
}
@Override
public void sendBasicNotification(TenantId tenantId, UserId recipientId, NotificationType type, String subject, String text) {
public void sendBasicNotification(TenantId tenantId, UserId recipientId, String subject, String text) {
Notification notification = Notification.builder()
.recipientId(recipientId)
.type(type)
.type(NotificationType.GENERAL)
.subject(subject)
.text(text)
.originatorType(NotificationOriginatorType.SYSTEM)

2
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationRuleProcessingService.java

@ -47,7 +47,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.executors.NotificationExecutorService;
import java.util.List;
import java.util.Map;
@Service
@TbCoreComponent
@ -135,7 +134,6 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
.tenantId(tenantId)
.targets(List.of(targetId))
.templateId(notificationRule.getTemplateId())
.deliveryMethods(notificationRule.getDeliveryMethods())
.additionalConfig(config)
.info(notificationInfo)
.ruleId(notificationRule.getId())

3
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java

@ -28,7 +28,6 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
@ -115,7 +114,7 @@ public class DefaultNotificationSchedulerService extends AbstractPartitionBasedS
log.error("Failed to process scheduled notification request {}", notificationRequest.getId(), e);
UserId senderId = notificationRequest.getSenderId();
if (senderId != null) {
notificationCenter.sendBasicNotification(tenantId, senderId, NotificationType.FAILURE, "Notification failure",
notificationCenter.sendBasicNotification(tenantId, senderId, "Notification failure",
"Failed to process scheduled notification (request " + notificationRequest.getId() + "): " + e.getMessage());
}
}

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

@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.notification.template.NotificationTemp
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings("unchecked")
public class NotificationProcessingContext {
@ -49,6 +50,8 @@ public class NotificationProcessingContext {
private final NotificationTemplate notificationTemplate;
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates;
@Getter
private Set<NotificationDeliveryMethod> deliveryMethods;
@Getter
private final NotificationRequestStats stats;
@Builder
@ -63,13 +66,13 @@ public class NotificationProcessingContext {
public void init() {
NotificationTemplateConfig templateConfig = notificationTemplate.getConfiguration();
templates = templateConfig.getTemplates();
for (NotificationDeliveryMethod deliveryMethod : request.getDeliveryMethods()) {
DeliveryMethodNotificationTemplate template = templates.get(deliveryMethod);
templates = templateConfig.getDeliveryMethodsTemplates();
templates.forEach((deliveryMethod, template) -> {
if (StringUtils.isEmpty(template.getBody())) {
template.setBody(templateConfig.getDefaultTextTemplate());
}
}
});
deliveryMethods = templates.keySet();
}
public <T extends DeliveryMethodNotificationTemplate> T getTemplate(NotificationDeliveryMethod deliveryMethod) {

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

@ -17,7 +17,6 @@ package org.thingsboard.server.service.notification.channels;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.thingsboard.rule.engine.api.MailService;
import org.thingsboard.server.common.data.User;
@ -36,16 +35,8 @@ public class EmailNotificationChannel implements NotificationChannel {
@Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) {
EmailDeliveryMethodNotificationTemplate template = ctx.getTemplate(NotificationDeliveryMethod.EMAIL);
String subject = template.getSubject();
if (StringUtils.isBlank(subject)) {
subject = ctx.getNotificationTemplate().getNotificationSubject();
}
if (StringUtils.isBlank(subject)) {
subject = ctx.getNotificationTemplate().getNotificationType().getName();
}
String mailSubject = subject;
return executor.submit(() -> {
mailService.sendEmail(recipient.getTenantId(), recipient.getEmail(), mailSubject, text);
mailService.sendEmail(recipient.getTenantId(), recipient.getEmail(), template.getSubject(), text);
return null;
});
}

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

@ -18,14 +18,12 @@ package org.thingsboard.server.service.notification.channels;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.thingsboard.rule.engine.api.slack.SlackService;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.notification.AlreadySentException;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.template.SlackConversation;
import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate;
import org.thingsboard.server.service.executors.ExternalCallExecutorService;
import org.thingsboard.server.service.notification.NotificationProcessingContext;
@ -39,33 +37,17 @@ public class SlackNotificationChannel implements NotificationChannel {
@Override
public ListenableFuture<Void> sendNotification(User recipient, String text, NotificationProcessingContext ctx) {
if (ctx.getStats().contains(NotificationDeliveryMethod.SLACK)) {
return Futures.immediateFailedFuture(new AlreadySentException());
}
SlackDeliveryMethodNotificationTemplate template = ctx.getTemplate(NotificationDeliveryMethod.SLACK);
SlackNotificationDeliveryMethodConfig config = ctx.getDeliveryMethodConfig(NotificationDeliveryMethod.SLACK);
if (StringUtils.isNotEmpty(template.getConversationId())) { // if conversationId is set, we only need to send message once
if (ctx.getStats().contains(NotificationDeliveryMethod.SLACK)) {
return Futures.immediateFailedFuture(new AlreadySentException());
} else {
return executor.submit(() -> {
slackService.sendMessage(ctx.getTenantId(), config.getBotToken(), template.getConversationId(), text);
return null;
});
}
} else {
if (StringUtils.isNoneEmpty(recipient.getFirstName(), recipient.getLastName())) {
String username = StringUtils.join(new String[]{recipient.getFirstName(), recipient.getLastName()}, ' ');
return executor.submit(() -> {
SlackConversation conversation = slackService.findConversation(recipient.getTenantId(), config.getBotToken(), SlackConversation.Type.DIRECT, username);
if (conversation == null) {
throw new IllegalArgumentException("Slack user not found for given name '" + username + "'");
}
slackService.sendMessage(ctx.getTenantId(), config.getBotToken(), conversation.getId(), text);
return null;
});
} else {
return Futures.immediateFailedFuture(new IllegalArgumentException("Couldn't determine Slack username for the user"));
}
}
return executor.submit(() -> {
slackService.sendMessage(ctx.getTenantId(), config.getBotToken(), template.getConversationId(), text);
return null;
});
}
@Override

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

@ -38,6 +38,8 @@ import org.thingsboard.server.common.data.notification.template.DeliveryMethodNo
import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate;
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.PushDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.notification.template.SmsDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
@ -63,7 +65,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
protected MailService mailService;
public static final String DEFAULT_NOTIFICATION_SUBJECT = "Just a test";
public static final NotificationType DEFAULT_NOTIFICATION_TYPE = NotificationType.ADMIN;
public static final NotificationType DEFAULT_NOTIFICATION_TYPE = NotificationType.GENERAL;
protected NotificationTarget createNotificationTarget(UserId... usersIds) {
NotificationTarget notificationTarget = new NotificationTarget();
@ -101,7 +103,6 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
.targets(targets)
.templateId(notificationTemplate.getId())
.info(notificationInfo)
.deliveryMethods(List.of(deliveryMethods))
.additionalConfig(config)
.build();
return doPost("/api/notification/request", notificationRequest, NotificationRequest.class);
@ -113,21 +114,32 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
notificationTemplate.setTenantId(tenantId);
notificationTemplate.setName("Notification template for testing");
notificationTemplate.setNotificationType(notificationType);
notificationTemplate.setNotificationSubject(subject);
NotificationTemplateConfig config = new NotificationTemplateConfig();
config.setDefaultTextTemplate(text);
config.setTemplates(new HashMap<>());
config.setDeliveryMethodsTemplates(new HashMap<>());
for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) {
if (deliveryMethod == NotificationDeliveryMethod.EMAIL) {
EmailDeliveryMethodNotificationTemplate emailNotificationTemplate = new EmailDeliveryMethodNotificationTemplate();
emailNotificationTemplate.setSubject("Hello from test");
emailNotificationTemplate.setMethod(deliveryMethod);
config.getTemplates().put(deliveryMethod, emailNotificationTemplate);
} else {
DeliveryMethodNotificationTemplate defaultTemplate = new DeliveryMethodNotificationTemplate();
defaultTemplate.setMethod(deliveryMethod);
config.getTemplates().put(deliveryMethod, defaultTemplate);
DeliveryMethodNotificationTemplate deliveryMethodNotificationTemplate;
switch (deliveryMethod) {
case PUSH: {
PushDeliveryMethodNotificationTemplate template = new PushDeliveryMethodNotificationTemplate();
template.setSubject(subject);
deliveryMethodNotificationTemplate = template;
break;
}
case EMAIL: {
EmailDeliveryMethodNotificationTemplate template = new EmailDeliveryMethodNotificationTemplate();
template.setSubject(subject);
deliveryMethodNotificationTemplate = template;
break;
}
case SMS: {
deliveryMethodNotificationTemplate = new SmsDeliveryMethodNotificationTemplate();
break;
}
default:
throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod);
}
config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate);
}
notificationTemplate.setConfiguration(config);
return doPost("/api/notification/template", notificationTemplate, NotificationTemplate.class);

5
application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java

@ -37,7 +37,6 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.notification.NotificationDao;
import org.thingsboard.server.dao.notification.NotificationRequestDao;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsCountUpdate;
@ -68,8 +67,6 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
@Autowired
private NotificationDao notificationDao;
@Autowired
private NotificationRequestDao notificationRequestDao;
@Autowired
private DbCallbackExecutorService executor;
@Before
@ -354,7 +351,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
@Test
public void testNotificationsForALotOfUsers() throws Exception {
int usersCount = 7000;
int usersCount = 5000;
List<User> users = new ArrayList<>();
for (int i = 1; i <= usersCount; i++) {

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

@ -45,7 +45,6 @@ public class NotificationTemplateApiTest extends AbstractControllerTest {
notificationTemplate.setTenantId(tenantId);
notificationTemplate.setName(null);
notificationTemplate.setNotificationType(null);
notificationTemplate.setNotificationSubject(null);
notificationTemplate.setConfiguration(null);
String validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
@ -58,10 +57,9 @@ public class NotificationTemplateApiTest extends AbstractControllerTest {
notificationTemplate.setConfiguration(config);
config.setDefaultTextTemplate("Default text");
EmailDeliveryMethodNotificationTemplate emailTemplate = new EmailDeliveryMethodNotificationTemplate();
emailTemplate.setMethod(NotificationDeliveryMethod.EMAIL);
emailTemplate.setBody(null);
emailTemplate.setSubject(null);
config.setTemplates(Map.of(
config.setDeliveryMethodsTemplates(Map.of(
NotificationDeliveryMethod.EMAIL, emailTemplate
));
notificationTemplate.setName("<script/>");
@ -69,6 +67,7 @@ public class NotificationTemplateApiTest extends AbstractControllerTest {
validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
assertThat(validationError)
.doesNotContain("defaultTextTemplate must be specified")
.contains("subject must not be")
.contains("name is malformed");
config.setDefaultTextTemplate(null);

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java

@ -16,5 +16,5 @@
package org.thingsboard.server.common.data.notification;
public enum NotificationDeliveryMethod {
PUSH, SMS, EMAIL, SLACK
PUSH, EMAIL, SMS, SLACK
}

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

@ -21,7 +21,6 @@ import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
@ -53,8 +52,6 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
private NotificationTemplateId templateId;
@Valid
private NotificationInfo info;
@NotEmpty
private List<NotificationDeliveryMethod> deliveryMethods;
@NotNull
@Valid
private NotificationRequestConfig additionalConfig;
@ -70,7 +67,7 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
@JsonIgnore
@Override
public String getName() {
return "To targets " + targets + " via " + StringUtils.join(deliveryMethods, ", ");
return "To targets " + targets;
}
@JsonIgnore

9
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java

@ -21,12 +21,9 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum NotificationType {
GENERIC("Generic"),
ADMIN("Admin"),
ALARM("Alarm"),
SCHEDULED_EVENT("Scheduled event"),
COMPLETED("Completed"),
FAILURE("Failure");
GENERAL("General"),
ALARM("Alarm");
private final String name;

15
common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/AccountNotificationSettings.java

@ -1,3 +1,18 @@
/**
* 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.settings;
import lombok.Data;

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

@ -17,23 +17,24 @@ package org.thingsboard.server.common.data.notification.template;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import javax.validation.constraints.NotNull;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "method", visible = true, include = JsonTypeInfo.As.EXISTING_PROPERTY, defaultImpl = DeliveryMethodNotificationTemplate.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "method")
@JsonSubTypes({
@JsonSubTypes.Type(name = "EMAIL", value = EmailDeliveryMethodNotificationTemplate.class),
@JsonSubTypes.Type(name = "SLACK", value = SlackDeliveryMethodNotificationTemplate.class)
@Type(name = "PUSH", value = PushDeliveryMethodNotificationTemplate.class),
@Type(name = "EMAIL", value = EmailDeliveryMethodNotificationTemplate.class),
@Type(name = "SMS", value = SmsDeliveryMethodNotificationTemplate.class),
@Type(name = "SLACK", value = SlackDeliveryMethodNotificationTemplate.class)
})
@Data
public class DeliveryMethodNotificationTemplate {
public abstract class DeliveryMethodNotificationTemplate {
private String body;
@NotNull
private NotificationDeliveryMethod method;
public abstract NotificationDeliveryMethod getMethod();
}

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

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

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java

@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.validation.NoXss;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ -40,7 +39,6 @@ public class NotificationTemplate extends BaseData<NotificationTemplateId> imple
@NoXss
@NotNull
private NotificationType notificationType;
private String notificationSubject;
@Valid
@NotNull
private NotificationTemplateConfig configuration; // TODO: add pg_tgrm index

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

@ -22,7 +22,6 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.Map;
@ -32,12 +31,12 @@ public class NotificationTemplateConfig {
private String defaultTextTemplate;
@Valid
@NotEmpty
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates;
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> deliveryMethodsTemplates;
@JsonIgnore
@AssertTrue(message = "defaultTextTemplate must be specified if one absent for delivery method")
public boolean isValid() {
if (templates.values().stream().anyMatch(template -> StringUtils.isEmpty(template.getBody()))) {
if (deliveryMethodsTemplates.values().stream().anyMatch(template -> StringUtils.isEmpty(template.getBody()))) {
return StringUtils.isNotEmpty(defaultTextTemplate);
} else {
return true;

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

@ -0,0 +1,35 @@
/**
* 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;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data
@EqualsAndHashCode(callSuper = true)
public class PushDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
private String subject;
private String icon;
private String actionButtonConfig;
@Override
public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.PUSH;
}
}

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

@ -17,14 +17,21 @@ package org.thingsboard.server.common.data.notification.template;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import java.util.Map;
import javax.validation.constraints.NotEmpty;
@Data
@EqualsAndHashCode(callSuper = true)
public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
private SlackConversation.Type conversationType;
private String conversationId; // not required, set from user's name if not set
@NotEmpty
private String conversationId;
@Override
public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.SLACK;
}
}

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

@ -0,0 +1,31 @@
/**
* 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;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@Data
@EqualsAndHashCode(callSuper = true)
public class SmsDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
@Override
public NotificationDeliveryMethod getMethod() {
return NotificationDeliveryMethod.SMS;
}
}

3
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -665,7 +665,6 @@ public class ModelConstants {
public static final String NOTIFICATION_REQUEST_TABLE_NAME = "notification_request";
public static final String NOTIFICATION_REQUEST_TARGETS_PROPERTY = "targets";
public static final String NOTIFICATION_REQUEST_TEMPLATE_ID_PROPERTY = "template_id";
public static final String NOTIFICATION_REQUEST_DELIVERY_METHODS_PROPERTY = "delivery_methods";
public static final String NOTIFICATION_REQUEST_INFO_PROPERTY = "info";
public static final String NOTIFICATION_REQUEST_ORIGINATOR_TYPE_PROPERTY = "originator_type";
public static final String NOTIFICATION_REQUEST_ORIGINATOR_ENTITY_ID_PROPERTY = "originator_entity_id";
@ -682,7 +681,6 @@ public class ModelConstants {
public static final String NOTIFICATION_TEMPLATE_TABLE_NAME = "notification_template";
public static final String NOTIFICATION_TEMPLATE_NOTIFICATION_TYPE_PROPERTY = "notification_type";
public static final String NOTIFICATION_TEMPLATE_NOTIFICATION_SUBJECT_PROPERTY = "notification_subject";
public static final String NOTIFICATION_TEMPLATE_CONFIGURATION_PROPERTY = "configuration";
protected static final String[] NONE_AGGREGATION_COLUMNS = new String[]{LONG_VALUE_COLUMN, DOUBLE_VALUE_COLUMN, BOOLEAN_VALUE_COLUMN, STRING_VALUE_COLUMN, JSON_VALUE_COLUMN, KEY_COLUMN, TS_COLUMN};
@ -731,4 +729,5 @@ public class ModelConstants {
throw new RuntimeException("Aggregation type: " + aggregation + " is not supported!");
}
}
}

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java

@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationInfo;
import org.thingsboard.server.common.data.notification.NotificationOriginatorType;
import org.thingsboard.server.common.data.notification.NotificationRequest;
@ -64,9 +63,6 @@ public class NotificationRequestEntity extends BaseSqlEntity<NotificationRequest
@Column(name = ModelConstants.NOTIFICATION_REQUEST_INFO_PROPERTY)
private JsonNode info;
@Column(name = ModelConstants.NOTIFICATION_REQUEST_DELIVERY_METHODS_PROPERTY, nullable = false)
private String deliveryMethods;
@Type(type = "json")
@Column(name = ModelConstants.NOTIFICATION_REQUEST_ADDITIONAL_CONFIG_PROPERTY)
private JsonNode additionalConfig;
@ -102,7 +98,6 @@ public class NotificationRequestEntity extends BaseSqlEntity<NotificationRequest
setTargets(listToString(notificationRequest.getTargets()));
setTemplateId(getUuid(notificationRequest.getTemplateId()));
setInfo(toJson(notificationRequest.getInfo()));
setDeliveryMethods(listToString(notificationRequest.getDeliveryMethods()));
setAdditionalConfig(toJson(notificationRequest.getAdditionalConfig()));
setOriginatorType(notificationRequest.getOriginatorType());
if (notificationRequest.getOriginatorEntityId() != null) {
@ -123,7 +118,6 @@ public class NotificationRequestEntity extends BaseSqlEntity<NotificationRequest
notificationRequest.setTargets(listFromString(targets, uuid -> new NotificationTargetId(UUID.fromString(uuid))));
notificationRequest.setTemplateId(getEntityId(templateId, NotificationTemplateId::new));
notificationRequest.setInfo(fromJson(info, NotificationInfo.class));
notificationRequest.setDeliveryMethods(listFromString(deliveryMethods, NotificationDeliveryMethod::valueOf));
notificationRequest.setAdditionalConfig(fromJson(additionalConfig, NotificationRequestConfig.class));
notificationRequest.setOriginatorType(originatorType);
if (originatorEntityId != null) {

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java

@ -21,7 +21,6 @@ import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
@ -53,9 +52,6 @@ public class NotificationTemplateEntity extends BaseSqlEntity<NotificationTempla
@Column(name = ModelConstants.NOTIFICATION_TEMPLATE_NOTIFICATION_TYPE_PROPERTY, nullable = false)
private NotificationType notificationType;
@Column(name = ModelConstants.NOTIFICATION_TEMPLATE_NOTIFICATION_SUBJECT_PROPERTY)
private String notificationSubject;
@Type(type = "json")
@Column(name = ModelConstants.NOTIFICATION_TEMPLATE_CONFIGURATION_PROPERTY, nullable = false)
private JsonNode configuration;
@ -68,7 +64,6 @@ public class NotificationTemplateEntity extends BaseSqlEntity<NotificationTempla
setTenantId(getTenantUuid(notificationTemplate.getTenantId()));
setName(notificationTemplate.getName());
setNotificationType(notificationTemplate.getNotificationType());
setNotificationSubject(notificationTemplate.getNotificationSubject());
setConfiguration(toJson(notificationTemplate.getConfiguration()));
}
@ -80,7 +75,6 @@ public class NotificationTemplateEntity extends BaseSqlEntity<NotificationTempla
notificationTemplate.setTenantId(getTenantId(tenantId));
notificationTemplate.setName(name);
notificationTemplate.setNotificationType(notificationType);
notificationTemplate.setNotificationSubject(notificationSubject);
notificationTemplate.setConfiguration(fromJson(configuration, NotificationTemplateConfig.class));
return notificationTemplate;
}

2
dao/src/main/resources/sql/schema-entities.sql

@ -794,7 +794,6 @@ CREATE TABLE IF NOT EXISTS notification_template (
tenant_id UUID NULL CONSTRAINT fk_notification_template_tenant_id REFERENCES tenant(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
notification_type VARCHAR(32) NOT NULL,
notification_subject VARCHAR(255),
configuration VARCHAR(10000) NOT NULL
);
@ -815,7 +814,6 @@ CREATE TABLE IF NOT EXISTS notification_request (
targets VARCHAR(10000) NOT NULL,
template_id UUID NOT NULL,
info VARCHAR(1000),
delivery_methods VARCHAR(255),
additional_config VARCHAR(1000),
originator_type VARCHAR(32) NOT NULL,
originator_entity_id UUID,

3
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NotificationCenter.java

@ -20,7 +20,6 @@ import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationType;
public interface NotificationCenter {
@ -30,7 +29,7 @@ public interface NotificationCenter {
NotificationRequest updateNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest);
void sendBasicNotification(TenantId tenantId, UserId recipientId, NotificationType type, String subject, String text);
void sendBasicNotification(TenantId tenantId, UserId recipientId, String subject, String text);
void markNotificationAsRead(TenantId tenantId, UserId recipientId, NotificationId notificationId);

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java

@ -60,7 +60,6 @@ public class TbNotificationNode implements TbNode {
.targets(config.getTargets())
.templateId(config.getTemplateId())
.info(notificationInfo)
.deliveryMethods(config.getDeliveryMethods())
.additionalConfig(new NotificationRequestConfig())
.originatorType(NotificationOriginatorType.RULE_NODE)
.originatorEntityId(ctx.getSelfId())

4
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java

@ -19,7 +19,6 @@ import lombok.Data;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
import javax.validation.constraints.NotEmpty;
@ -33,14 +32,11 @@ public class TbNotificationNodeConfiguration implements NodeConfiguration<TbNoti
private List<NotificationTargetId> targets;
@NotNull
private NotificationTemplateId templateId;
@NotEmpty
private List<NotificationDeliveryMethod> deliveryMethods;
private NotificationRequestConfig additionalConfig;
@Override
public TbNotificationNodeConfiguration defaultConfiguration() {
TbNotificationNodeConfiguration config = new TbNotificationNodeConfiguration();
config.setDeliveryMethods(List.of(NotificationDeliveryMethod.PUSH));
config.setAdditionalConfig(new NotificationRequestConfig());
return config;
}

Loading…
Cancel
Save