Recipient preview for notification request; template params functions
This commit is contained in:
parent
8705a2324e
commit
cda1836986
@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.thingsboard.rule.engine.api.NotificationCenter;
|
import org.thingsboard.rule.engine.api.NotificationCenter;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
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.exception.ThingsboardException;
|
||||||
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;
|
||||||
@ -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.id.TenantId;
|
||||||
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.NotificationProcessingContext;
|
import org.thingsboard.server.service.notification.NotificationProcessingContext;
|
||||||
import org.thingsboard.server.common.data.notification.NotificationRequest;
|
import org.thingsboard.server.common.data.notification.NotificationRequest;
|
||||||
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
|
import org.thingsboard.server.common.data.notification.NotificationRequestInfo;
|
||||||
import org.thingsboard.server.common.data.notification.NotificationRequestPreview;
|
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 javax.validation.Valid;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -196,6 +199,7 @@ public class NotificationController extends BaseController {
|
|||||||
@PostMapping("/notification/request/preview")
|
@PostMapping("/notification/request/preview")
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
|
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
|
||||||
public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request,
|
public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request,
|
||||||
|
@RequestParam(defaultValue = "20") int recipientsPreviewSize,
|
||||||
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
|
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
|
||||||
NotificationRequestPreview preview = new NotificationRequestPreview();
|
NotificationRequestPreview preview = new NotificationRequestPreview();
|
||||||
|
|
||||||
@ -229,18 +233,29 @@ public class NotificationController extends BaseController {
|
|||||||
preview.setProcessedTemplates(processedTemplates);
|
preview.setProcessedTemplates(processedTemplates);
|
||||||
|
|
||||||
// generic permission
|
// generic permission
|
||||||
|
Set<User> recipientsPreview = new LinkedHashSet<>();
|
||||||
Map<String, Integer> recipientsCountByTarget = new HashMap<>();
|
Map<String, Integer> recipientsCountByTarget = new HashMap<>();
|
||||||
List<NotificationTarget> targets = notificationTargetService.findNotificationTargetsByTenantIdAndIds(user.getTenantId(),
|
List<NotificationTarget> targets = notificationTargetService.findNotificationTargetsByTenantIdAndIds(user.getTenantId(),
|
||||||
request.getTargets().stream().map(NotificationTargetId::new).collect(Collectors.toList()));
|
request.getTargets().stream().map(NotificationTargetId::new).collect(Collectors.toList()));
|
||||||
for (NotificationTarget target : targets) {
|
for (NotificationTarget target : targets) {
|
||||||
int recipientsCount;
|
int recipientsCount;
|
||||||
if (target.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) {
|
if (target.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) {
|
||||||
recipientsCount = notificationTargetService.countRecipientsForNotificationTargetConfig(user.getTenantId(), target.getConfiguration());
|
PageData<User> 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 {
|
} else {
|
||||||
recipientsCount = 1;
|
recipientsCount = 1;
|
||||||
}
|
}
|
||||||
recipientsCountByTarget.put(target.getName(), recipientsCount);
|
recipientsCountByTarget.put(target.getName(), recipientsCount);
|
||||||
}
|
}
|
||||||
|
preview.setRecipientsPreview(recipientsPreview);
|
||||||
preview.setRecipientsCountByTarget(recipientsCountByTarget);
|
preview.setRecipientsCountByTarget(recipientsCountByTarget);
|
||||||
preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum());
|
preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum());
|
||||||
|
|
||||||
|
|||||||
@ -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.AlreadySentException;
|
||||||
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.NotificationProcessingContext;
|
|
||||||
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.NotificationRequestStats;
|
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
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.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.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.NotificationInfo;
|
||||||
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
|
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
|
||||||
import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig;
|
import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig;
|
||||||
@ -40,6 +43,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class NotificationProcessingContext {
|
public class NotificationProcessingContext {
|
||||||
@ -58,6 +62,8 @@ public class NotificationProcessingContext {
|
|||||||
@Getter
|
@Getter
|
||||||
private final NotificationRequestStats stats;
|
private final NotificationRequestStats stats;
|
||||||
|
|
||||||
|
private static final Pattern TEMPLATE_PARAM_PATTERN = Pattern.compile("\\$\\{([a-zA-Z]+)(:[a-zA-Z]+)?}");
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public NotificationProcessingContext(TenantId tenantId, NotificationRequest request, NotificationSettings settings,
|
public NotificationProcessingContext(TenantId tenantId, NotificationRequest request, NotificationSettings settings,
|
||||||
NotificationTemplate template) {
|
NotificationTemplate template) {
|
||||||
@ -111,7 +117,7 @@ public class NotificationProcessingContext {
|
|||||||
}
|
}
|
||||||
JsonNode link = buttonConfig.get().get("link");
|
JsonNode link = buttonConfig.get().get("link");
|
||||||
if (link != null && link.isTextual()) {
|
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);
|
buttonConfig.get().set("link", link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,19 +126,22 @@ public class NotificationProcessingContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String processTemplate(String template, Map<String, String> context) {
|
private static String processTemplate(String template, Map<String, String> context) {
|
||||||
if (template == null) return null;
|
return TEMPLATE_PARAM_PATTERN.matcher(template).replaceAll(matchResult -> {
|
||||||
String result = template;
|
String key = matchResult.group(1);
|
||||||
for (Map.Entry<String, String> kv : context.entrySet()) {
|
String value = Strings.nullToEmpty(context.get(key));
|
||||||
String value = Strings.nullToEmpty(kv.getValue());
|
String function = matchResult.group(2);
|
||||||
result = result.replace("${" + kv.getKey() + '}', value);
|
if (function != null) {
|
||||||
}
|
switch (function) {
|
||||||
return result;
|
case ":upperCase":
|
||||||
}
|
return value.toUpperCase();
|
||||||
|
case ":lowerCase":
|
||||||
public static String processTemplate(String template, NotificationInfo notificationInfo) {
|
return value.toLowerCase();
|
||||||
if (notificationInfo == null) return template;
|
case ":capitalize":
|
||||||
Map<String, String> templateContext = notificationInfo.getTemplateData();
|
return StringUtils.capitalize(value.toLowerCase());
|
||||||
return processTemplate(template, templateContext);
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> createTemplateContext(User recipient) {
|
public Map<String, String> createTemplateContext(User recipient) {
|
||||||
@ -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.NotificationDeliveryMethod;
|
||||||
import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate;
|
import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate;
|
||||||
import org.thingsboard.server.service.mail.MailExecutorService;
|
import org.thingsboard.server.service.mail.MailExecutorService;
|
||||||
import org.thingsboard.server.common.data.notification.NotificationProcessingContext;
|
import org.thingsboard.server.service.notification.NotificationProcessingContext;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
|||||||
@ -17,7 +17,7 @@ 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.notification.NotificationDeliveryMethod;
|
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.targets.NotificationRecipient;
|
||||||
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
|
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.thingsboard.rule.engine.api.slack.SlackService;
|
import org.thingsboard.rule.engine.api.slack.SlackService;
|
||||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
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.settings.SlackNotificationDeliveryMethodConfig;
|
||||||
import org.thingsboard.server.common.data.notification.targets.slack.SlackConversation;
|
import org.thingsboard.server.common.data.notification.targets.slack.SlackConversation;
|
||||||
import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate;
|
import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate;
|
||||||
|
|||||||
@ -24,7 +24,7 @@ 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.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;
|
import org.thingsboard.server.service.sms.SmsExecutorService;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
|||||||
@ -132,7 +132,6 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
|
|||||||
notificationTemplate.setName("Notification template: " + text);
|
notificationTemplate.setName("Notification template: " + text);
|
||||||
notificationTemplate.setNotificationType(notificationType);
|
notificationTemplate.setNotificationType(notificationType);
|
||||||
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
||||||
config.setDefaultTextTemplate(text);
|
|
||||||
config.setDeliveryMethodsTemplates(new HashMap<>());
|
config.setDeliveryMethodsTemplates(new HashMap<>());
|
||||||
for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) {
|
for (NotificationDeliveryMethod deliveryMethod : deliveryMethods) {
|
||||||
DeliveryMethodNotificationTemplate deliveryMethodNotificationTemplate;
|
DeliveryMethodNotificationTemplate deliveryMethodNotificationTemplate;
|
||||||
@ -157,6 +156,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest
|
|||||||
throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod);
|
throw new IllegalArgumentException("Unsupported delivery method " + deliveryMethod);
|
||||||
}
|
}
|
||||||
deliveryMethodNotificationTemplate.setEnabled(true);
|
deliveryMethodNotificationTemplate.setEnabled(true);
|
||||||
|
deliveryMethodNotificationTemplate.setBody(text);
|
||||||
config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate);
|
config.getDeliveryMethodsTemplates().put(deliveryMethod, deliveryMethodNotificationTemplate);
|
||||||
}
|
}
|
||||||
notificationTemplate.setConfiguration(config);
|
notificationTemplate.setConfiguration(config);
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.thingsboard.rule.engine.api.NotificationCenter;
|
import org.thingsboard.rule.engine.api.NotificationCenter;
|
||||||
import org.thingsboard.server.common.data.User;
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.id.NotificationTargetId;
|
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.Notification;
|
||||||
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;
|
||||||
@ -339,6 +340,8 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
target1Config.setUsersFilter(userListFilter);
|
target1Config.setUsersFilter(userListFilter);
|
||||||
target1.setConfiguration(target1Config);
|
target1.setConfiguration(target1Config);
|
||||||
target1 = saveNotificationTarget(target1);
|
target1 = saveNotificationTarget(target1);
|
||||||
|
List<UserId> recipients = new ArrayList<>();
|
||||||
|
recipients.add(tenantAdminUserId);
|
||||||
|
|
||||||
createDifferentCustomer();
|
createDifferentCustomer();
|
||||||
loginTenantAdmin();
|
loginTenantAdmin();
|
||||||
@ -350,6 +353,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
customerUser.setCustomerId(differentCustomerId);
|
customerUser.setCustomerId(differentCustomerId);
|
||||||
customerUser.setEmail("other-customer-" + i + "@thingsboard.org");
|
customerUser.setEmail("other-customer-" + i + "@thingsboard.org");
|
||||||
customerUser = createUser(customerUser, "12345678");
|
customerUser = createUser(customerUser, "12345678");
|
||||||
|
recipients.add(customerUser.getId());
|
||||||
}
|
}
|
||||||
NotificationTarget target2 = new NotificationTarget();
|
NotificationTarget target2 = new NotificationTarget();
|
||||||
target2.setName("Other customer users");
|
target2.setName("Other customer users");
|
||||||
@ -367,27 +371,25 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
|
|
||||||
String requestorEmail = TENANT_ADMIN_EMAIL;
|
String requestorEmail = TENANT_ADMIN_EMAIL;
|
||||||
NotificationTemplateConfig templateConfig = new NotificationTemplateConfig();
|
NotificationTemplateConfig templateConfig = new NotificationTemplateConfig();
|
||||||
templateConfig.setDefaultTextTemplate("Default message for SMS and WEB: ${recipientEmail}");
|
|
||||||
templateConfig.setNotificationSubject("Default subject for EMAIL: ${recipientEmail}");
|
|
||||||
HashMap<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates = new HashMap<>();
|
HashMap<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> templates = new HashMap<>();
|
||||||
templateConfig.setDeliveryMethodsTemplates(templates);
|
templateConfig.setDeliveryMethodsTemplates(templates);
|
||||||
notificationTemplate.setConfiguration(templateConfig);
|
notificationTemplate.setConfiguration(templateConfig);
|
||||||
|
|
||||||
WebDeliveryMethodNotificationTemplate webNotificationTemplate = new WebDeliveryMethodNotificationTemplate();
|
WebDeliveryMethodNotificationTemplate webNotificationTemplate = new WebDeliveryMethodNotificationTemplate();
|
||||||
webNotificationTemplate.setEnabled(true);
|
webNotificationTemplate.setEnabled(true);
|
||||||
// using default message for web
|
webNotificationTemplate.setBody("Message for WEB: ${recipientEmail}");
|
||||||
webNotificationTemplate.setSubject("Subject for WEB: ${recipientEmail}");
|
webNotificationTemplate.setSubject("Subject for WEB: ${recipientEmail}");
|
||||||
templates.put(NotificationDeliveryMethod.WEB, webNotificationTemplate);
|
templates.put(NotificationDeliveryMethod.WEB, webNotificationTemplate);
|
||||||
|
|
||||||
SmsDeliveryMethodNotificationTemplate smsNotificationTemplate = new SmsDeliveryMethodNotificationTemplate();
|
SmsDeliveryMethodNotificationTemplate smsNotificationTemplate = new SmsDeliveryMethodNotificationTemplate();
|
||||||
smsNotificationTemplate.setEnabled(true);
|
smsNotificationTemplate.setEnabled(true);
|
||||||
// using default message for sms
|
smsNotificationTemplate.setBody("Message for SMS: ${recipientEmail}");
|
||||||
templates.put(NotificationDeliveryMethod.SMS, smsNotificationTemplate);
|
templates.put(NotificationDeliveryMethod.SMS, smsNotificationTemplate);
|
||||||
|
|
||||||
EmailDeliveryMethodNotificationTemplate emailNotificationTemplate = new EmailDeliveryMethodNotificationTemplate();
|
EmailDeliveryMethodNotificationTemplate emailNotificationTemplate = new EmailDeliveryMethodNotificationTemplate();
|
||||||
emailNotificationTemplate.setEnabled(true);
|
emailNotificationTemplate.setEnabled(true);
|
||||||
|
emailNotificationTemplate.setSubject("Subject for EMAIL: ${recipientEmail}");
|
||||||
emailNotificationTemplate.setBody("Message for EMAIL: ${recipientEmail}");
|
emailNotificationTemplate.setBody("Message for EMAIL: ${recipientEmail}");
|
||||||
// using default subject for email
|
|
||||||
templates.put(NotificationDeliveryMethod.EMAIL, emailNotificationTemplate);
|
templates.put(NotificationDeliveryMethod.EMAIL, emailNotificationTemplate);
|
||||||
|
|
||||||
SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate();
|
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(target1.getName())).isEqualTo(1);
|
||||||
assertThat(preview.getRecipientsCountByTarget().get(target2.getName())).isEqualTo(customerUsersCount);
|
assertThat(preview.getRecipientsCountByTarget().get(target2.getName())).isEqualTo(customerUsersCount);
|
||||||
assertThat(preview.getTotalRecipientsCount()).isEqualTo(1 + customerUsersCount);
|
assertThat(preview.getTotalRecipientsCount()).isEqualTo(1 + customerUsersCount);
|
||||||
|
assertThat(preview.getRecipientsPreview()).extracting(User::getId).containsAll(recipients);
|
||||||
|
|
||||||
Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates = preview.getProcessedTemplates();
|
Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates = preview.getProcessedTemplates();
|
||||||
assertThat(processedTemplates.get(NotificationDeliveryMethod.WEB)).asInstanceOf(type(WebDeliveryMethodNotificationTemplate.class))
|
assertThat(processedTemplates.get(NotificationDeliveryMethod.WEB)).asInstanceOf(type(WebDeliveryMethodNotificationTemplate.class))
|
||||||
.satisfies(template -> {
|
.satisfies(template -> {
|
||||||
assertThat(template.getBody())
|
assertThat(template.getBody())
|
||||||
.startsWith("Default message for SMS and WEB")
|
.startsWith("Message for WEB")
|
||||||
.endsWith(requestorEmail);
|
.endsWith(requestorEmail);
|
||||||
assertThat(template.getSubject())
|
assertThat(template.getSubject())
|
||||||
.startsWith("Subject for WEB")
|
.startsWith("Subject for WEB")
|
||||||
@ -421,7 +424,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
assertThat(processedTemplates.get(NotificationDeliveryMethod.SMS)).asInstanceOf(type(SmsDeliveryMethodNotificationTemplate.class))
|
assertThat(processedTemplates.get(NotificationDeliveryMethod.SMS)).asInstanceOf(type(SmsDeliveryMethodNotificationTemplate.class))
|
||||||
.satisfies(template -> {
|
.satisfies(template -> {
|
||||||
assertThat(template.getBody())
|
assertThat(template.getBody())
|
||||||
.startsWith("Default message for SMS and WEB")
|
.startsWith("Message for SMS")
|
||||||
.endsWith(requestorEmail);
|
.endsWith(requestorEmail);
|
||||||
});
|
});
|
||||||
assertThat(processedTemplates.get(NotificationDeliveryMethod.EMAIL)).asInstanceOf(type(EmailDeliveryMethodNotificationTemplate.class))
|
assertThat(processedTemplates.get(NotificationDeliveryMethod.EMAIL)).asInstanceOf(type(EmailDeliveryMethodNotificationTemplate.class))
|
||||||
@ -430,7 +433,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
.startsWith("Message for EMAIL")
|
.startsWith("Message for EMAIL")
|
||||||
.endsWith(requestorEmail);
|
.endsWith(requestorEmail);
|
||||||
assertThat(template.getSubject())
|
assertThat(template.getSubject())
|
||||||
.startsWith("Default subject for EMAIL")
|
.startsWith("Subject for EMAIL")
|
||||||
.endsWith(requestorEmail);
|
.endsWith(requestorEmail);
|
||||||
});
|
});
|
||||||
assertThat(processedTemplates.get(NotificationDeliveryMethod.SLACK)).asInstanceOf(type(SlackDeliveryMethodNotificationTemplate.class))
|
assertThat(processedTemplates.get(NotificationDeliveryMethod.SLACK)).asInstanceOf(type(SlackDeliveryMethodNotificationTemplate.class))
|
||||||
@ -534,9 +537,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
notificationTemplate.setName("Slack notification template");
|
notificationTemplate.setName("Slack notification template");
|
||||||
notificationTemplate.setNotificationType(NotificationType.GENERAL);
|
notificationTemplate.setNotificationType(NotificationType.GENERAL);
|
||||||
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
||||||
config.setDefaultTextTemplate("To Slack :) ${recipientEmail}");
|
|
||||||
SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate();
|
SlackDeliveryMethodNotificationTemplate slackNotificationTemplate = new SlackDeliveryMethodNotificationTemplate();
|
||||||
slackNotificationTemplate.setEnabled(true);
|
slackNotificationTemplate.setEnabled(true);
|
||||||
|
slackNotificationTemplate.setBody("To Slack :) ${recipientEmail}");
|
||||||
config.setDeliveryMethodsTemplates(Map.of(
|
config.setDeliveryMethodsTemplates(Map.of(
|
||||||
NotificationDeliveryMethod.SLACK, slackNotificationTemplate
|
NotificationDeliveryMethod.SLACK, slackNotificationTemplate
|
||||||
));
|
));
|
||||||
@ -556,7 +559,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
NotificationRequest successfulNotificationRequest = submitNotificationRequest(List.of(notificationTarget.getId()), notificationTemplate.getId(), 0);
|
NotificationRequest successfulNotificationRequest = submitNotificationRequest(List.of(notificationTarget.getId()), notificationTemplate.getId(), 0);
|
||||||
await().atMost(2, TimeUnit.SECONDS)
|
await().atMost(2, TimeUnit.SECONDS)
|
||||||
.until(() -> findNotificationRequest(successfulNotificationRequest.getId()).isSent());
|
.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());
|
NotificationRequestStats stats = getStats(successfulNotificationRequest.getId());
|
||||||
assertThat(stats.getSent().get(NotificationDeliveryMethod.SLACK)).hasValue(1);
|
assertThat(stats.getSent().get(NotificationDeliveryMethod.SLACK)).hasValue(1);
|
||||||
|
|
||||||
|
|||||||
@ -75,6 +75,8 @@ import org.thingsboard.server.common.data.script.ScriptLanguage;
|
|||||||
import org.thingsboard.server.common.data.security.Authority;
|
import org.thingsboard.server.common.data.security.Authority;
|
||||||
import org.thingsboard.server.dao.alarm.AlarmService;
|
import org.thingsboard.server.dao.alarm.AlarmService;
|
||||||
import org.thingsboard.server.dao.notification.NotificationRequestService;
|
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.dao.service.DaoSqlTest;
|
||||||
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
|
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
|
||||||
|
|
||||||
@ -103,6 +105,10 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
|||||||
private AlarmSubscriptionService alarmSubscriptionService;
|
private AlarmSubscriptionService alarmSubscriptionService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private NotificationRequestService notificationRequestService;
|
private NotificationRequestService notificationRequestService;
|
||||||
|
@Autowired
|
||||||
|
private NotificationRuleService notificationRuleService;
|
||||||
|
@Autowired
|
||||||
|
private NotificationTemplateService notificationTemplateService;
|
||||||
|
|
||||||
@SpyBean
|
@SpyBean
|
||||||
private AlarmService alarmService;
|
private AlarmService alarmService;
|
||||||
@ -110,7 +116,8 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
|||||||
@Before
|
@Before
|
||||||
public void beforeEach() throws Exception {
|
public void beforeEach() throws Exception {
|
||||||
loginTenantAdmin();
|
loginTenantAdmin();
|
||||||
|
notificationRuleService.deleteNotificationRulesByTenantId(tenantId);
|
||||||
|
notificationTemplateService.deleteNotificationTemplatesByTenantId(tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -226,7 +233,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
|||||||
assertThat(actualDelay).isCloseTo(expectedDelay, offset(0.5));
|
assertThat(actualDelay).isCloseTo(expectedDelay, offset(0.5));
|
||||||
|
|
||||||
AlarmStatus expectedStatus = AlarmStatus.ACTIVE_UNACK;
|
AlarmStatus expectedStatus = AlarmStatus.ACTIVE_UNACK;
|
||||||
AlarmSeverity expectedSeverity = AlarmSeverity.CRITICAL;
|
String expectedSeverity = AlarmSeverity.CRITICAL.toString().toLowerCase();
|
||||||
|
|
||||||
assertThat(notification.getSubject()).isEqualTo("Alarm type: " + alarmType + ", status: " + expectedStatus + ", " +
|
assertThat(notification.getSubject()).isEqualTo("Alarm type: " + alarmType + ", status: " + expectedStatus + ", " +
|
||||||
"severity: " + expectedSeverity + ", deviceId: " + device.getId());
|
"severity: " + expectedSeverity + ", deviceId: " + device.getId());
|
||||||
@ -304,7 +311,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
|||||||
getWsClient().waitForUpdate(true);
|
getWsClient().waitForUpdate(true);
|
||||||
|
|
||||||
Notification notification = getWsClient().getLastDataUpdate().getUpdate();
|
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))
|
assertThat(notification.getInfo()).asInstanceOf(type(AlarmNotificationInfo.class))
|
||||||
.extracting(AlarmNotificationInfo::getAlarmId).isEqualTo(alarm.getUuidId());
|
.extracting(AlarmNotificationInfo::getAlarmId).isEqualTo(alarm.getUuidId());
|
||||||
|
|
||||||
@ -323,48 +330,6 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
|
|||||||
assertThat(findNotificationRequests(EntityType.ALARM).getData()).filteredOn(NotificationRequest::isScheduled).isEmpty();
|
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
|
@Test
|
||||||
public void testNotificationRuleInfo() throws Exception {
|
public void testNotificationRuleInfo() throws Exception {
|
||||||
NotificationDeliveryMethod[] deliveryMethods = {NotificationDeliveryMethod.WEB, NotificationDeliveryMethod.EMAIL};
|
NotificationDeliveryMethod[] deliveryMethods = {NotificationDeliveryMethod.WEB, NotificationDeliveryMethod.EMAIL};
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.test.web.servlet.ResultActions;
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
import org.springframework.test.web.servlet.ResultMatcher;
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
import org.thingsboard.server.common.data.id.IdBased;
|
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.notification.template.NotificationTemplateConfig;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
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 org.thingsboard.server.dao.service.DaoSqlTest;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -40,9 +43,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
@DaoSqlTest
|
@DaoSqlTest
|
||||||
public class NotificationTemplateApiTest extends AbstractNotificationApiTest {
|
public class NotificationTemplateApiTest extends AbstractNotificationApiTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NotificationTemplateService templateService;
|
||||||
|
@Autowired
|
||||||
|
private NotificationRuleService notificationRuleService;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeEach() throws Exception {
|
public void beforeEach() throws Exception {
|
||||||
loginTenantAdmin();
|
loginTenantAdmin();
|
||||||
|
notificationRuleService.deleteNotificationRulesByTenantId(tenantId);
|
||||||
|
templateService.deleteNotificationTemplatesByTenantId(tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -61,8 +71,6 @@ public class NotificationTemplateApiTest extends AbstractNotificationApiTest {
|
|||||||
|
|
||||||
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
NotificationTemplateConfig config = new NotificationTemplateConfig();
|
||||||
notificationTemplate.setConfiguration(config);
|
notificationTemplate.setConfiguration(config);
|
||||||
config.setDefaultTextTemplate("Default text");
|
|
||||||
config.setNotificationSubject(null);
|
|
||||||
EmailDeliveryMethodNotificationTemplate emailTemplate = new EmailDeliveryMethodNotificationTemplate();
|
EmailDeliveryMethodNotificationTemplate emailTemplate = new EmailDeliveryMethodNotificationTemplate();
|
||||||
emailTemplate.setEnabled(true);
|
emailTemplate.setEnabled(true);
|
||||||
emailTemplate.setBody(null);
|
emailTemplate.setBody(null);
|
||||||
@ -74,14 +82,9 @@ public class NotificationTemplateApiTest extends AbstractNotificationApiTest {
|
|||||||
|
|
||||||
validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
|
validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
|
||||||
assertThat(validationError)
|
assertThat(validationError)
|
||||||
.contains("notificationSubject must be")
|
.contains("subject must not be")
|
||||||
|
.contains("body must not be")
|
||||||
.contains("name is malformed");
|
.contains("name is malformed");
|
||||||
|
|
||||||
config.setDefaultTextTemplate(null);
|
|
||||||
|
|
||||||
validationError = saveAndGetError(notificationTemplate, status().isBadRequest());
|
|
||||||
assertThat(validationError)
|
|
||||||
.contains("defaultTextTemplate").contains("must be specified");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -16,8 +16,10 @@
|
|||||||
package org.thingsboard.server.common.data.notification;
|
package org.thingsboard.server.common.data.notification;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
|
import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -26,5 +28,6 @@ public class NotificationRequestPreview {
|
|||||||
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates;
|
private Map<NotificationDeliveryMethod, DeliveryMethodNotificationTemplate> processedTemplates;
|
||||||
private int totalRecipientsCount;
|
private int totalRecipientsCount;
|
||||||
private Map<String, Integer> recipientsCountByTarget;
|
private Map<String, Integer> recipientsCountByTarget;
|
||||||
|
private Collection<User> recipientsPreview;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user