diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java index e4e37a7788..a6f69d7079 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java @@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationRequestId; @@ -38,7 +39,7 @@ import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import org.thingsboard.server.common.data.notification.NotificationProcessingContext; +import org.thingsboard.server.service.notification.NotificationProcessingContext; import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequestInfo; import org.thingsboard.server.common.data.notification.NotificationRequestPreview; @@ -62,8 +63,10 @@ import org.thingsboard.server.service.security.permission.Operation; import javax.validation.Valid; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -196,6 +199,7 @@ public class NotificationController extends BaseController { @PostMapping("/notification/request/preview") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request, + @RequestParam(defaultValue = "20") int recipientsPreviewSize, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { NotificationRequestPreview preview = new NotificationRequestPreview(); @@ -229,18 +233,29 @@ public class NotificationController extends BaseController { preview.setProcessedTemplates(processedTemplates); // generic permission + Set recipientsPreview = new LinkedHashSet<>(); Map recipientsCountByTarget = new HashMap<>(); List targets = notificationTargetService.findNotificationTargetsByTenantIdAndIds(user.getTenantId(), request.getTargets().stream().map(NotificationTargetId::new).collect(Collectors.toList())); for (NotificationTarget target : targets) { int recipientsCount; if (target.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) { - recipientsCount = notificationTargetService.countRecipientsForNotificationTargetConfig(user.getTenantId(), target.getConfiguration()); + PageData recipients = notificationTargetService.findRecipientsForNotificationTargetConfig(user.getTenantId(), null, + target.getConfiguration(), new PageLink(recipientsPreviewSize)); + recipientsCount = (int) recipients.getTotalElements(); + for (User recipient : recipients.getData()) { + if (recipientsPreview.size() < recipientsPreviewSize) { + recipientsPreview.add(recipient); + } else { + break; + } + } } else { recipientsCount = 1; } recipientsCountByTarget.put(target.getName(), recipientsCount); } + preview.setRecipientsPreview(recipientsPreview); preview.setRecipientsCountByTarget(recipientsCountByTarget); preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum()); diff --git a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java index 05fa07af51..4f13072504 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java @@ -33,7 +33,6 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.AlreadySentException; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import org.thingsboard.server.common.data.notification.NotificationProcessingContext; import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequestConfig; import org.thingsboard.server.common.data.notification.NotificationRequestStats; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java b/application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java similarity index 84% rename from common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java rename to application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java index 119b4a473e..5492650d48 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.notification; +package org.thingsboard.server.service.notification; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -25,6 +25,9 @@ import org.apache.commons.lang3.StringUtils; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; +import org.thingsboard.server.common.data.notification.NotificationRequest; +import org.thingsboard.server.common.data.notification.NotificationRequestStats; import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo; import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig; @@ -40,6 +43,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.regex.Pattern; @SuppressWarnings("unchecked") public class NotificationProcessingContext { @@ -58,6 +62,8 @@ public class NotificationProcessingContext { @Getter private final NotificationRequestStats stats; + private static final Pattern TEMPLATE_PARAM_PATTERN = Pattern.compile("\\$\\{([a-zA-Z]+)(:[a-zA-Z]+)?}"); + @Builder public NotificationProcessingContext(TenantId tenantId, NotificationRequest request, NotificationSettings settings, NotificationTemplate template) { @@ -111,7 +117,7 @@ public class NotificationProcessingContext { } JsonNode link = buttonConfig.get().get("link"); if (link != null && link.isTextual()) { - link = new TextNode(processTemplate(link.asText(), templateContext).toLowerCase()); + link = new TextNode(processTemplate(link.asText(), templateContext)); buttonConfig.get().set("link", link); } } @@ -120,19 +126,22 @@ public class NotificationProcessingContext { } private static String processTemplate(String template, Map context) { - if (template == null) return null; - String result = template; - for (Map.Entry kv : context.entrySet()) { - String value = Strings.nullToEmpty(kv.getValue()); - result = result.replace("${" + kv.getKey() + '}', value); - } - return result; - } - - public static String processTemplate(String template, NotificationInfo notificationInfo) { - if (notificationInfo == null) return template; - Map templateContext = notificationInfo.getTemplateData(); - return processTemplate(template, templateContext); + return TEMPLATE_PARAM_PATTERN.matcher(template).replaceAll(matchResult -> { + String key = matchResult.group(1); + String value = Strings.nullToEmpty(context.get(key)); + String function = matchResult.group(2); + if (function != null) { + switch (function) { + case ":upperCase": + return value.toUpperCase(); + case ":lowerCase": + return value.toLowerCase(); + case ":capitalize": + return StringUtils.capitalize(value.toLowerCase()); + } + } + return value; + }); } public Map createTemplateContext(User recipient) { diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java index be80d9d75c..ce9c6e3b98 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/EmailNotificationChannel.java @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate; import org.thingsboard.server.service.mail.MailExecutorService; -import org.thingsboard.server.common.data.notification.NotificationProcessingContext; +import org.thingsboard.server.service.notification.NotificationProcessingContext; @Component @RequiredArgsConstructor diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/NotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/NotificationChannel.java index 0357cccf3a..7e82d31c27 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/NotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/NotificationChannel.java @@ -17,7 +17,7 @@ package org.thingsboard.server.service.notification.channels; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import org.thingsboard.server.common.data.notification.NotificationProcessingContext; +import org.thingsboard.server.service.notification.NotificationProcessingContext; import org.thingsboard.server.common.data.notification.targets.NotificationRecipient; import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java index 2c9d948fb8..67108c2a37 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/SlackNotificationChannel.java @@ -20,7 +20,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.thingsboard.rule.engine.api.slack.SlackService; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import org.thingsboard.server.common.data.notification.NotificationProcessingContext; +import org.thingsboard.server.service.notification.NotificationProcessingContext; import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.targets.slack.SlackConversation; import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/SmsNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/SmsNotificationChannel.java index 5d97d73a90..b49f1a9b73 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/SmsNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/SmsNotificationChannel.java @@ -24,7 +24,7 @@ import org.thingsboard.rule.engine.api.SmsService; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.template.SmsDeliveryMethodNotificationTemplate; -import org.thingsboard.server.common.data.notification.NotificationProcessingContext; +import org.thingsboard.server.service.notification.NotificationProcessingContext; import org.thingsboard.server.service.sms.SmsExecutorService; @Component diff --git a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java index 7988b5ae2e..7bbd88445f 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java @@ -132,7 +132,6 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest notificationTemplate.setName("Notification template: " + text); notificationTemplate.setNotificationType(notificationType); NotificationTemplateConfig config = new NotificationTemplateConfig(); - config.setDefaultTextTemplate(text); config.setDeliveryMethodsTemplates(new HashMap<>()); for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) { DeliveryMethodNotificationTemplate deliveryMethodNotificationTemplate; @@ -157,6 +156,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod); } deliveryMethodNotificationTemplate.setEnabled(true); + deliveryMethodNotificationTemplate.setBody(text); config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate); } notificationTemplate.setConfiguration(config); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index f9c9f2836b..7d318f5522 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.NotificationTargetId; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationRequest; @@ -339,6 +340,8 @@ public class NotificationApiTest extends AbstractNotificationApiTest { target1Config.setUsersFilter(userListFilter); target1.setConfiguration(target1Config); target1 = saveNotificationTarget(target1); + List recipients = new ArrayList<>(); + recipients.add(tenantAdminUserId); createDifferentCustomer(); loginTenantAdmin(); @@ -350,6 +353,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { customerUser.setCustomerId(differentCustomerId); customerUser.setEmail("other-customer-" + i + "@thingsboard.org"); customerUser = createUser(customerUser, "12345678"); + recipients.add(customerUser.getId()); } NotificationTarget target2 = new NotificationTarget(); target2.setName("Other customer users"); @@ -367,27 +371,25 @@ public class NotificationApiTest extends AbstractNotificationApiTest { String requestorEmail = TENANT_ADMIN_EMAIL; NotificationTemplateConfig templateConfig = new NotificationTemplateConfig(); - templateConfig.setDefaultTextTemplate("Default message for SMS and WEB: ${recipientEmail}"); - templateConfig.setNotificationSubject("Default subject for EMAIL: ${recipientEmail}"); HashMap templates = new HashMap<>(); templateConfig.setDeliveryMethodsTemplates(templates); notificationTemplate.setConfiguration(templateConfig); WebDeliveryMethodNotificationTemplate webNotificationTemplate = new WebDeliveryMethodNotificationTemplate(); webNotificationTemplate.setEnabled(true); - // using default message for web + webNotificationTemplate.setBody("Message for WEB: ${recipientEmail}"); webNotificationTemplate.setSubject("Subject for WEB: ${recipientEmail}"); templates.put(NotificationDeliveryMethod.WEB, webNotificationTemplate); SmsDeliveryMethodNotificationTemplate smsNotificationTemplate = new SmsDeliveryMethodNotificationTemplate(); smsNotificationTemplate.setEnabled(true); - // using default message for sms + smsNotificationTemplate.setBody("Message for SMS: ${recipientEmail}"); templates.put(NotificationDeliveryMethod.SMS, smsNotificationTemplate); EmailDeliveryMethodNotificationTemplate emailNotificationTemplate = new EmailDeliveryMethodNotificationTemplate(); emailNotificationTemplate.setEnabled(true); + emailNotificationTemplate.setSubject("Subject for EMAIL: ${recipientEmail}"); emailNotificationTemplate.setBody("Message for EMAIL: ${recipientEmail}"); - // using default subject for email templates.put(NotificationDeliveryMethod.EMAIL, emailNotificationTemplate); SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate(); @@ -407,12 +409,13 @@ public class NotificationApiTest extends AbstractNotificationApiTest { assertThat(preview.getRecipientsCountByTarget().get(target1.getName())).isEqualTo(1); assertThat(preview.getRecipientsCountByTarget().get(target2.getName())).isEqualTo(customerUsersCount); assertThat(preview.getTotalRecipientsCount()).isEqualTo(1 + customerUsersCount); + assertThat(preview.getRecipientsPreview()).extracting(User::getId).containsAll(recipients); Map processedTemplates = preview.getProcessedTemplates(); assertThat(processedTemplates.get(NotificationDeliveryMethod.WEB)).asInstanceOf(type(WebDeliveryMethodNotificationTemplate.class)) .satisfies(template -> { assertThat(template.getBody()) - .startsWith("Default message for SMS and WEB") + .startsWith("Message for WEB") .endsWith(requestorEmail); assertThat(template.getSubject()) .startsWith("Subject for WEB") @@ -421,7 +424,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { assertThat(processedTemplates.get(NotificationDeliveryMethod.SMS)).asInstanceOf(type(SmsDeliveryMethodNotificationTemplate.class)) .satisfies(template -> { assertThat(template.getBody()) - .startsWith("Default message for SMS and WEB") + .startsWith("Message for SMS") .endsWith(requestorEmail); }); assertThat(processedTemplates.get(NotificationDeliveryMethod.EMAIL)).asInstanceOf(type(EmailDeliveryMethodNotificationTemplate.class)) @@ -430,7 +433,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { .startsWith("Message for EMAIL") .endsWith(requestorEmail); assertThat(template.getSubject()) - .startsWith("Default subject for EMAIL") + .startsWith("Subject for EMAIL") .endsWith(requestorEmail); }); assertThat(processedTemplates.get(NotificationDeliveryMethod.SLACK)).asInstanceOf(type(SlackDeliveryMethodNotificationTemplate.class)) @@ -534,9 +537,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest { notificationTemplate.setName("Slack notification template"); notificationTemplate.setNotificationType(NotificationType.GENERAL); NotificationTemplateConfig config = new NotificationTemplateConfig(); - config.setDefaultTextTemplate("To Slack :) ${recipientEmail}"); SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate(); slackNotificationTemplate.setEnabled(true); + slackNotificationTemplate.setBody("To Slack :) ${recipientEmail}"); config.setDeliveryMethodsTemplates(Map.of( NotificationDeliveryMethod.SLACK, slackNotificationTemplate )); @@ -556,7 +559,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { NotificationRequest successfulNotificationRequest = submitNotificationRequest(List.of(notificationTarget.getId()), notificationTemplate.getId(), 0); await().atMost(2, TimeUnit.SECONDS) .until(() -> findNotificationRequest(successfulNotificationRequest.getId()).isSent()); - verify(slackService).sendMessage(eq(tenantId), eq(slackToken), eq(conversationId), eq(config.getDefaultTextTemplate())); + verify(slackService).sendMessage(eq(tenantId), eq(slackToken), eq(conversationId), eq(slackNotificationTemplate.getBody())); NotificationRequestStats stats = getStats(successfulNotificationRequest.getId()); assertThat(stats.getSent().get(NotificationDeliveryMethod.SLACK)).hasValue(1); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java index f1a76b147a..f355d9072c 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java @@ -75,6 +75,8 @@ import org.thingsboard.server.common.data.script.ScriptLanguage; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.notification.NotificationRequestService; +import org.thingsboard.server.dao.notification.NotificationRuleService; +import org.thingsboard.server.dao.notification.NotificationTemplateService; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; @@ -103,6 +105,10 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { private AlarmSubscriptionService alarmSubscriptionService; @Autowired private NotificationRequestService notificationRequestService; + @Autowired + private NotificationRuleService notificationRuleService; + @Autowired + private NotificationTemplateService notificationTemplateService; @SpyBean private AlarmService alarmService; @@ -110,7 +116,8 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { @Before public void beforeEach() throws Exception { loginTenantAdmin(); - + notificationRuleService.deleteNotificationRulesByTenantId(tenantId); + notificationTemplateService.deleteNotificationTemplatesByTenantId(tenantId); } @Test @@ -226,7 +233,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { assertThat(actualDelay).isCloseTo(expectedDelay, offset(0.5)); AlarmStatus expectedStatus = AlarmStatus.ACTIVE_UNACK; - AlarmSeverity expectedSeverity = AlarmSeverity.CRITICAL; + String expectedSeverity = AlarmSeverity.CRITICAL.toString().toLowerCase(); assertThat(notification.getSubject()).isEqualTo("Alarm type: " + alarmType + ", status: " + expectedStatus + ", " + "severity: " + expectedSeverity + ", deviceId: " + device.getId()); @@ -304,7 +311,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { getWsClient().waitForUpdate(true); Notification notification = getWsClient().getLastDataUpdate().getUpdate(); - assertThat(notification.getSubject()).isEqualTo("CRITICAL alarm '" + alarmType + "' is ACTIVE_UNACK"); + assertThat(notification.getSubject()).isEqualTo("critical alarm '" + alarmType + "' is ACTIVE_UNACK"); assertThat(notification.getInfo()).asInstanceOf(type(AlarmNotificationInfo.class)) .extracting(AlarmNotificationInfo::getAlarmId).isEqualTo(alarm.getUuidId()); @@ -323,48 +330,6 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { assertThat(findNotificationRequests(EntityType.ALARM).getData()).filteredOn(NotificationRequest::isScheduled).isEmpty(); } - @Test - public void testNotificationRuleProcessing_ruleEngineComponentLifecycleEvent_ruleNodeStartError() { - String subject = "Rule Node '${componentName}' in Rule Chain '${ruleChainName}' failed to start"; - String text = "The error: ${error}"; - NotificationTemplate template = createNotificationTemplate(NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, subject, text, NotificationDeliveryMethod.WEB); - - NotificationRule rule = new NotificationRule(); - rule.setName("Rule node start-up failures in my rule chain"); - rule.setTemplateId(template.getId()); - rule.setTriggerType(NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT); - - RuleChain ruleChain = createEmptyRuleChain("My Rule Chain"); - var triggerConfig = new RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig(); - triggerConfig.setRuleChains(Set.of(ruleChain.getUuidId())); - triggerConfig.setRuleChainEvents(Set.of(ComponentLifecycleEvent.STARTED)); - triggerConfig.setOnlyRuleChainLifecycleFailures(true); - - triggerConfig.setTrackRuleNodeEvents(true); - triggerConfig.setRuleNodeEvents(Set.of(ComponentLifecycleEvent.STARTED)); - triggerConfig.setOnlyRuleNodeLifecycleFailures(true); - rule.setTriggerConfig(triggerConfig); - - NotificationTarget target = createNotificationTarget(tenantAdminUserId); - DefaultNotificationRuleRecipientsConfig recipientsConfig = new DefaultNotificationRuleRecipientsConfig(); - recipientsConfig.setTriggerType(NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT); - recipientsConfig.setTargets(List.of(target.getUuidId())); - rule.setRecipientsConfig(recipientsConfig); - rule = saveNotificationRule(rule); - - getWsClient().subscribeForUnreadNotifications(10).waitForReply(true); - getWsClient().registerWaitForUpdate(); - - addRuleNodeWithError(ruleChain.getId(), "My generator"); - - getWsClient().waitForUpdate(10000, true); - Notification notification = getWsClient().getLastDataUpdate().getUpdate(); - - assertThat(notification.getType()).isEqualTo(NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT); - assertThat(notification.getSubject()).isEqualTo("Rule Node 'My generator' in Rule Chain 'My Rule Chain' failed to start"); - assertThat(notification.getText()).startsWith("The error: Can't compile script"); - } - @Test public void testNotificationRuleInfo() throws Exception { NotificationDeliveryMethod[] deliveryMethods = {NotificationDeliveryMethod.WEB, NotificationDeliveryMethod.EMAIL}; diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java index 67a7fd8bd4..1b843d61b4 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationTemplateApiTest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.lang3.StringUtils; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultMatcher; import org.thingsboard.server.common.data.id.IdBased; @@ -29,6 +30,8 @@ import org.thingsboard.server.common.data.notification.template.NotificationTemp import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.notification.NotificationRuleService; +import org.thingsboard.server.dao.notification.NotificationTemplateService; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.List; @@ -40,9 +43,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DaoSqlTest public class NotificationTemplateApiTest extends AbstractNotificationApiTest { + @Autowired + private NotificationTemplateService templateService; + @Autowired + private NotificationRuleService notificationRuleService; + @Before public void beforeEach() throws Exception { loginTenantAdmin(); + notificationRuleService.deleteNotificationRulesByTenantId(tenantId); + templateService.deleteNotificationTemplatesByTenantId(tenantId); } @Test @@ -61,8 +71,6 @@ public class NotificationTemplateApiTest extends AbstractNotificationApiTest { NotificationTemplateConfig config = new NotificationTemplateConfig(); notificationTemplate.setConfiguration(config); - config.setDefaultTextTemplate("Default text"); - config.setNotificationSubject(null); EmailDeliveryMethodNotificationTemplate emailTemplate = new EmailDeliveryMethodNotificationTemplate(); emailTemplate.setEnabled(true); emailTemplate.setBody(null); @@ -74,14 +82,9 @@ public class NotificationTemplateApiTest extends AbstractNotificationApiTest { validationError = saveAndGetError(notificationTemplate, status().isBadRequest()); assertThat(validationError) - .contains("notificationSubject must be") + .contains("subject must not be") + .contains("body must not be") .contains("name is malformed"); - - config.setDefaultTextTemplate(null); - - validationError = saveAndGetError(notificationTemplate, status().isBadRequest()); - assertThat(validationError) - .contains("defaultTextTemplate").contains("must be specified"); } @Test diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestPreview.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestPreview.java index 82319196f5..2e3ff0fd99 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestPreview.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestPreview.java @@ -16,8 +16,10 @@ package org.thingsboard.server.common.data.notification; import lombok.Data; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate; +import java.util.Collection; import java.util.Map; @Data @@ -26,5 +28,6 @@ public class NotificationRequestPreview { private Map processedTemplates; private int totalRecipientsCount; private Map recipientsCountByTarget; + private Collection recipientsPreview; }