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 bd03040b3f..66c1940be4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.controller; +import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; @@ -77,6 +78,54 @@ public class NotificationController extends BaseController { private final NotificationCenter notificationCenter; private final NotificationSettingsService notificationSettingsService; + @ApiOperation(value = "Get notifications (getNotifications)", + notes = "**WebSocket API**:\n\n" + + "There are 2 types of subscriptions: one for unread notifications count, another for unread notifications themselves.\n\n" + + "The URI for opening WS session for notifications: `/api/ws/plugins/notifications`.\n\n" + + "Subscription command for unread notifications count:\n" + + "```\n{\n \"unreadCountSubCmd\": {\n \"cmdId\": 1234\n }\n}\n```\n" + + "To subscribe for latest unread notifications:\n" + + "```\n{\n \"unreadSubCmd\": {\n \"cmdId\": 1234,\n \"limit\": 10\n }\n}\n```\n" + + "To unsubscribe from any subscription:\n" + + "```\n{\n \"unsubCmd\": {\n \"cmdId\": 1234\n }\n}\n```\n" + + "To mark certain notifications as read, use following command:\n" + + "```\n{\n \"markAsReadCmd\": {\n \"cmdId\": 1234,\n \"notifications\": [\n \"6f860330-7fc2-11ed-b855-7dd3b7d2faa9\",\n \"5b6dfee0-8d0d-11ed-b61f-35a57b03dade\"\n ]\n }\n}\n\n```\n" + + "\n\n" + + "Update structure for unread **notifications count subscription**:\n" + + "```\n{\n \"cmdId\": 1234,\n \"totalUnreadCount\": 55\n}\n```\n" + + "For **notifications subscription**:\n" + + "- full update of latest unread notifications:\n" + + "```\n{\n" + + " \"cmdId\": 1234,\n" + + " \"notifications\": [\n" + + " {\n" + + " \"id\": {\n" + + " \"entityType\": \"NOTIFICATION\",\n" + + " \"id\": \"6f860330-7fc2-11ed-b855-7dd3b7d2faa9\"\n" + + " },\n" + + " ...\n" + + " }\n" + + " ],\n" + + " \"totalUnreadCount\": 1\n" + + "}\n```\n" + + "- when new notification arrives or shown notification is updated:\n" + + "```\n{\n" + + " \"cmdId\": 1234,\n" + + " \"update\": {\n" + + " \"id\": {\n" + + " \"entityType\": \"NOTIFICATION\",\n" + + " \"id\": \"6f860330-7fc2-11ed-b855-7dd3b7d2faa9\"\n" + + " },\n" + + " # updated notification info, text, subject etc.\n" + + " ...\n" + + " },\n" + + " \"totalUnreadCount\": 2\n" + + "}\n```\n" + + "- when unread notifications count changes:\n" + + "```\n{\n" + + " \"cmdId\": 1234,\n" + + " \"totalUnreadCount\": 5\n" + + "}\n```" ) @GetMapping("/notifications") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") public PageData getNotifications(@RequestParam int pageSize, diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java index 5a0c7f97a6..92543e4424 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.NotificationTemplateId; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; @@ -104,9 +105,14 @@ public class NotificationTemplateController extends BaseController { @RequestParam(required = false) String textSearch, @RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortOrder, + @RequestParam(required = false) NotificationType[] notificationTypes, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); - return notificationTemplateService.findNotificationTemplatesByTenantId(user.getTenantId(), pageLink); + if (notificationTypes == null || notificationTypes.length == 0) { + notificationTypes = NotificationType.values(); + } + return notificationTemplateService.findNotificationTemplatesByTenantIdAndNotificationTypes(user.getTenantId(), + List.of(notificationTypes), pageLink); } @ApiOperation(value = "Delete notification template by id (deleteNotificationTemplateById", diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java index c13cae9ab8..9d46ddda16 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java @@ -34,9 +34,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequestConfig; import org.thingsboard.server.common.data.notification.NotificationRequestStatus; -import org.thingsboard.server.common.data.notification.info.AlarmOriginatedNotificationInfo; import org.thingsboard.server.common.data.notification.info.NotificationInfo; -import org.thingsboard.server.common.data.notification.info.RuleEngineOriginatedNotificationInfo; import org.thingsboard.server.common.data.notification.rule.NotificationRule; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; @@ -53,7 +51,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.function.Supplier; import java.util.stream.Collectors; @Service @@ -85,48 +82,30 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul return; } - processTrigger(tenantId, triggerType, ruleEngineMsg.getOriginator(), ruleEngineMsg, false, () -> { - return RuleEngineOriginatedNotificationInfo.builder() - .msgOriginator(ruleEngineMsg.getOriginator()) - .msgType(ruleEngineMsg.getType()) - .msgMetadata(ruleEngineMsg.getMetaData().getData()) - .build(); - }); + processTrigger(tenantId, triggerType, ruleEngineMsg.getOriginator(), ruleEngineMsg, false); } @Override public void process(TenantId tenantId, Alarm alarm, boolean deleted) { - processTrigger(tenantId, NotificationRuleTriggerType.ALARM, alarm.getId(), alarm, deleted, () -> { - // TODO: add info about assignee - return AlarmOriginatedNotificationInfo.builder() - .alarmId(alarm.getId()) - .alarmType(alarm.getType()) - .alarmOriginator(alarm.getOriginator()) - .alarmSeverity(alarm.getSeverity()) - .alarmStatus(alarm.getStatus()) - .customerId(alarm.getCustomerId()) - .build(); - }); + processTrigger(tenantId, NotificationRuleTriggerType.ALARM, alarm.getId(), alarm, deleted); } private void processTrigger(TenantId tenantId, NotificationRuleTriggerType triggerType, EntityId originatorEntityId, - Object triggerObject, boolean triggerRemoved, - Supplier notificationInfoProvider) { + Object triggerObject, boolean triggerRemoved) { ListenableFuture> rulesFuture = dbCallbackExecutor.submit(() -> { return notificationRuleService.findNotificationRulesByTenantIdAndTriggerType(tenantId, triggerType); }); DonAsynchron.withCallback(rulesFuture, rules -> { for (NotificationRule rule : rules) { notificationExecutor.submit(() -> { - processNotificationRule(rule, originatorEntityId, triggerObject, triggerRemoved, notificationInfoProvider); + processNotificationRule(rule, originatorEntityId, triggerObject, triggerRemoved); }); } }, e -> {}); } private void processNotificationRule(NotificationRule rule, EntityId originatorEntityId, - T triggerObject, boolean triggerRemoved, - Supplier notificationInfoProvider) { + T triggerObject, boolean triggerRemoved) { NotificationRuleTriggerConfig triggerConfig = rule.getTriggerConfig(); log.debug("Processing notification rule '{}' for trigger type {}", rule.getName(), rule.getTriggerType()); @@ -149,7 +128,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul // not returning because we need to update notifications if any } - NotificationInfo notificationInfo = notificationInfoProvider.get(); + NotificationInfo notificationInfo = constructNotificationInfo(triggerObject, triggerConfig); for (NotificationRequest notificationRequest : notificationRequests) { NotificationInfo previousNotificationInfo = notificationRequest.getInfo(); if (!notificationInfo.equals(previousNotificationInfo)) { @@ -168,7 +147,7 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul return; } - NotificationInfo notificationInfo = notificationInfoProvider.get(); + NotificationInfo notificationInfo = constructNotificationInfo(triggerObject, triggerConfig); rule.getRecipientsConfig().getTargetsTable().forEach((delay, targets) -> { notificationExecutor.submit(() -> { try { @@ -189,6 +168,10 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul return triggerProcessors.get(triggerConfig.getTriggerType()).matchesClearRule(triggerObject, triggerConfig); } + private NotificationInfo constructNotificationInfo(Object triggerObject, NotificationRuleTriggerConfig triggerConfig) { + return triggerProcessors.get(triggerConfig.getTriggerType()).constructNotificationInfo(triggerObject, triggerConfig); + } + private void submitNotificationRequest(List targets, NotificationRule rule, EntityId originatorEntityId, NotificationInfo notificationInfo, int delayInSec) { NotificationRequestConfig config = new NotificationRequestConfig(); diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmNotificationRuleTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmNotificationRuleTriggerProcessor.java index 8e392b76bc..f69e8c5b6b 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmNotificationRuleTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmNotificationRuleTriggerProcessor.java @@ -18,6 +18,8 @@ package org.thingsboard.server.service.notification.rule.trigger; import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.notification.info.AlarmNotificationInfo; +import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; @@ -41,6 +43,18 @@ public class AlarmNotificationRuleTriggerProcessor implements NotificationRuleTr return false; } + @Override + public NotificationInfo constructNotificationInfo(Alarm alarm, AlarmNotificationRuleTriggerConfig triggerConfig) { + return AlarmNotificationInfo.builder() + .alarmId(alarm.getUuidId()) + .alarmType(alarm.getType()) + .alarmOriginator(alarm.getOriginator()) + .alarmSeverity(alarm.getSeverity()) + .alarmStatus(alarm.getStatus()) + .customerId(alarm.getCustomerId()) + .build(); + } + @Override public NotificationRuleTriggerType getTriggerType() { return NotificationRuleTriggerType.ALARM; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceInactivityNotificationRuleTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceInactivityNotificationRuleTriggerProcessor.java index abc84c2803..2e389f2b67 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceInactivityNotificationRuleTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceInactivityNotificationRuleTriggerProcessor.java @@ -21,6 +21,8 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.notification.info.DeviceInactivityNotificationInfo; +import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.rule.trigger.DeviceInactivityNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; import org.thingsboard.server.common.msg.TbMsg; @@ -45,6 +47,15 @@ public class DeviceInactivityNotificationRuleTriggerProcessor implements Notific } } + @Override + public NotificationInfo constructNotificationInfo(TbMsg ruleEngineMsg, DeviceInactivityNotificationRuleTriggerConfig triggerConfig) { + return DeviceInactivityNotificationInfo.builder() + .deviceId(ruleEngineMsg.getOriginator().getId()) + .deviceName(ruleEngineMsg.getMetaData().getValue("deviceName")) + .deviceType(ruleEngineMsg.getMetaData().getValue("deviceType")) + .build(); + } + @Override public NotificationRuleTriggerType getTriggerType() { return NotificationRuleTriggerType.DEVICE_INACTIVITY; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntityActionNotificationRuleTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntityActionNotificationRuleTriggerProcessor.java index 90326f86ef..7429134faf 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntityActionNotificationRuleTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntityActionNotificationRuleTriggerProcessor.java @@ -17,10 +17,16 @@ package org.thingsboard.server.service.notification.rule.trigger; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.notification.info.EntityActionNotificationInfo; +import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.rule.trigger.EntityActionNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; import org.thingsboard.server.common.msg.TbMsg; +import java.util.UUID; + @Service public class EntityActionNotificationRuleTriggerProcessor implements NotificationRuleTriggerProcessor { @@ -35,7 +41,7 @@ public class EntityActionNotificationRuleTriggerProcessor implements Notificatio if (!triggerConfig.isUpdated()) { return false; } - } else if (msgType.equals(DataConstants.ENTITY_DELETED)){ + } else if (msgType.equals(DataConstants.ENTITY_DELETED)) { if (!triggerConfig.isDeleted()) { return false; } @@ -45,6 +51,22 @@ public class EntityActionNotificationRuleTriggerProcessor implements Notificatio return triggerConfig.getEntityType() == null || ruleEngineMsg.getOriginator().getEntityType() == triggerConfig.getEntityType(); } + @Override + public NotificationInfo constructNotificationInfo(TbMsg ruleEngineMsg, EntityActionNotificationRuleTriggerConfig triggerConfig) { + EntityId entityId = ruleEngineMsg.getOriginator(); + String msgType = ruleEngineMsg.getType(); + ActionType actionType = msgType.equals(DataConstants.ENTITY_CREATED) ? ActionType.ADDED : + msgType.equals(DataConstants.ENTITY_UPDATED) ? ActionType.UPDATED : + msgType.equals(DataConstants.ENTITY_DELETED) ? ActionType.DELETED : null; + return EntityActionNotificationInfo.builder() + .entityType(entityId.getEntityType()) + .entityId(entityId.getId()) + .actionType(actionType) + .userId(UUID.fromString(ruleEngineMsg.getMetaData().getValue("userId"))) + .userName(ruleEngineMsg.getMetaData().getValue("userName")) + .build(); + } + @Override public NotificationRuleTriggerType getTriggerType() { return NotificationRuleTriggerType.ENTITY_ACTION; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/NotificationRuleTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/NotificationRuleTriggerProcessor.java index ed28c4ba6c..bf67179761 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/NotificationRuleTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/NotificationRuleTriggerProcessor.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.notification.rule.trigger; +import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; @@ -26,6 +27,8 @@ public interface NotificationRuleTriggerProcessor findTemplates(NotificationType... notificationTypes) throws Exception { + PageLink pageLink = new PageLink(100, 0); + return doGetTypedWithPageLink("/api/notification/templates?notificationTypes=" + StringUtils.join(notificationTypes, ",") + "&", + new TypeReference>() {}, pageLink).getData(); + } + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateService.java index bc1b95a37b..c595e4bb5f 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateService.java @@ -17,17 +17,20 @@ package org.thingsboard.server.dao.notification; 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.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import java.util.List; + public interface NotificationTemplateService { NotificationTemplate findNotificationTemplateById(TenantId tenantId, NotificationTemplateId id); NotificationTemplate saveNotificationTemplate(TenantId tenantId, NotificationTemplate notificationTemplate); - PageData findNotificationTemplatesByTenantId(TenantId tenantId, PageLink pageLink); + PageData findNotificationTemplatesByTenantIdAndNotificationTypes(TenantId tenantId, List notificationTypes, PageLink pageLink); void deleteNotificationTemplateById(TenantId tenantId, NotificationTemplateId id); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java index a102f763a7..4c41b45b15 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java @@ -22,7 +22,7 @@ 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.info.AlarmOriginatedNotificationInfo; +import org.thingsboard.server.common.data.notification.info.AlarmNotificationInfo; import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.settings.NotificationSettings; @@ -129,7 +129,7 @@ public class NotificationProcessingContext { CustomerId customerId; switch (request.getOriginatorEntityId().getEntityType()) { case ALARM: - customerId = ((AlarmOriginatedNotificationInfo) request.getInfo()).getCustomerId(); + customerId = ((AlarmNotificationInfo) request.getInfo()).getCustomerId(); break; default: customerId = null; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java index 5cbc908295..b5023ee42e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationType.java @@ -15,16 +15,11 @@ */ package org.thingsboard.server.common.data.notification; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter public enum NotificationType { - GENERAL("General"), - ALARM("Alarm"); - - private final String name; + GENERAL, + ALARM, + DEVICE_INACTIVITY, + ENTITY_ACTION; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmOriginatedNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java similarity index 92% rename from common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmOriginatedNotificationInfo.java rename to common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java index 98eeb2211e..b595b6dde6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmOriginatedNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java @@ -22,20 +22,20 @@ import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; -import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import java.util.Map; +import java.util.UUID; @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class AlarmOriginatedNotificationInfo implements NotificationInfo { +public class AlarmNotificationInfo implements NotificationInfo { - private AlarmId alarmId; private String alarmType; + private UUID alarmId; private EntityId alarmOriginator; private AlarmSeverity alarmSeverity; private AlarmStatus alarmStatus; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/DeviceInactivityNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/DeviceInactivityNotificationInfo.java new file mode 100644 index 0000000000..dd5fc89b0a --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/DeviceInactivityNotificationInfo.java @@ -0,0 +1,51 @@ +/** + * 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.info; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.thingsboard.server.common.data.EntityType; + +import java.util.Map; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class DeviceInactivityNotificationInfo implements NotificationInfo { + + private UUID deviceId; + private String deviceName; + private String deviceType; + + @Override + public EntityType getOriginatorType() { + return EntityType.DEVICE; + } + + @Override + public Map getTemplateData() { + return Map.of( + "deviceId", deviceId.toString(), + "deviceName", deviceName, + "deviceType", deviceType + ); + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java new file mode 100644 index 0000000000..df4917f4a5 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java @@ -0,0 +1,57 @@ +/** + * 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.info; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.audit.ActionType; + +import java.util.Map; +import java.util.UUID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class EntityActionNotificationInfo implements NotificationInfo { + + private EntityType entityType; + private UUID entityId; + private ActionType actionType; + private UUID userId; + private String userName; + // maybe add entityName and other info (from TbMsg data) + + @Override + public EntityType getOriginatorType() { + return EntityType.TENANT; + } + + @Override + public Map getTemplateData() { + return Map.of( + "entityType", entityType.name(), + "entityId", entityId.toString(), + "actionType", actionType.name(), + "userId", userId.toString(), + "userName", userName + ); + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/NotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/NotificationInfo.java index 3c60cd2330..56441da434 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/NotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/NotificationInfo.java @@ -21,19 +21,25 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.UserId; +import java.util.Collections; +import java.util.List; import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "originatorType") @JsonSubTypes({ @Type(name = "USER", value = UserOriginatedNotificationInfo.class), - @Type(name = "ALARM", value = AlarmOriginatedNotificationInfo.class), - @Type(name = "RULE_CHAIN", value = RuleEngineOriginatedNotificationInfo.class) + @Type(name = "ALARM", value = AlarmNotificationInfo.class), + @Type(name = "RULE_CHAIN", value = RuleEngineOriginatedNotificationInfo.class), + @Type(name = "DEVICE", value = DeviceInactivityNotificationInfo.class), + @Type(name = "TENANT", value = EntityActionNotificationInfo.class) }) public interface NotificationInfo { - EntityType getOriginatorType(); + @JsonIgnore + EntityType getOriginatorType(); // FIXME: originatorType is bad identifier, might have 2 types of info related to device @JsonIgnore Map getTemplateData(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/UserOriginatedNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/UserOriginatedNotificationInfo.java index f1607b44c0..318bcf1c71 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/UserOriginatedNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/UserOriginatedNotificationInfo.java @@ -17,7 +17,6 @@ package org.thingsboard.server.common.data.notification.info; import lombok.Data; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.DashboardId; import java.util.Collections; import java.util.Map; @@ -26,7 +25,6 @@ import java.util.Map; public class UserOriginatedNotificationInfo implements NotificationInfo { private String description; - private DashboardId dashboardId; @Override public EntityType getOriginatorType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetConfig.java index 5b6e49dfb4..225665c776 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetConfig.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.notification.targets; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; @@ -33,6 +34,7 @@ public abstract class NotificationTargetConfig { private String description; + @JsonIgnore public abstract NotificationTargetConfigType getType(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java index b5d60e13ee..82e21d1388 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java @@ -20,11 +20,13 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.id.NotificationTemplateId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.NotificationRequestStatus; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.AbstractEntityService; +import java.util.List; import java.util.Map; @Service @@ -45,8 +47,8 @@ public class DefaultNotificationTemplateService extends AbstractEntityService im } @Override - public PageData findNotificationTemplatesByTenantId(TenantId tenantId, PageLink pageLink) { - return notificationTemplateDao.findByTenantIdAndPageLink(tenantId, pageLink); + public PageData findNotificationTemplatesByTenantIdAndNotificationTypes(TenantId tenantId, List notificationTypes, PageLink pageLink) { + return notificationTemplateDao.findByTenantIdAndNotificationTypesAndPageLink(tenantId, notificationTypes, pageLink); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java b/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java index 489c35d6a8..0bd5b624d2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java @@ -16,13 +16,16 @@ package org.thingsboard.server.dao.notification; 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.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.Dao; +import java.util.List; + public interface NotificationTemplateDao extends Dao { - PageData findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink); + PageData findByTenantIdAndNotificationTypesAndPageLink(TenantId tenantId, List notificationTypes, PageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java index 7942decb6a..54870b18e0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java @@ -21,6 +21,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityType; 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.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -30,6 +31,7 @@ import org.thingsboard.server.dao.notification.NotificationTemplateDao; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.util.SqlDao; +import java.util.List; import java.util.UUID; import static org.thingsboard.server.dao.DaoUtil.getId; @@ -47,9 +49,9 @@ public class JpaNotificationTemplateDao extends JpaAbstractDao findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) { - return DaoUtil.toPageData(notificationTemplateRepository.findByTenantIdAndSearchText(getId(tenantId, true), - Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink))); + public PageData findByTenantIdAndNotificationTypesAndPageLink(TenantId tenantId, List notificationTypes, PageLink pageLink) { + return DaoUtil.toPageData(notificationTemplateRepository.findByTenantIdAndNotificationTypesAndSearchText(getId(tenantId, true), + notificationTypes, Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink))); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java index abfa0cdf59..43b074b57c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java @@ -21,18 +21,22 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.dao.model.sql.NotificationTemplateEntity; +import java.util.List; import java.util.UUID; @Repository public interface NotificationTemplateRepository extends JpaRepository { @Query("SELECT t FROM NotificationTemplateEntity t WHERE t.tenantId = :tenantId AND " + + "t.notificationType IN :notificationTypes AND " + "(lower(t.name) LIKE lower(concat('%', :searchText, '%')) OR " + "lower(t.notificationType) LIKE lower(concat('%', :searchText, '%')))") - Page findByTenantIdAndSearchText(@Param("tenantId") UUID tenantId, - @Param("searchText") String searchText, - Pageable pageable); + Page findByTenantIdAndNotificationTypesAndSearchText(@Param("tenantId") UUID tenantId, + @Param("notificationTypes") List notificationTypes, + @Param("searchText") String searchText, + Pageable pageable); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java index 9f48ff1690..e0fc17bc6d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java @@ -50,9 +50,11 @@ public class TbNotificationNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { - RuleEngineOriginatedNotificationInfo notificationInfo = new RuleEngineOriginatedNotificationInfo(); - notificationInfo.setMsgOriginator(msg.getOriginator()); - notificationInfo.setMsgMetadata(msg.getMetaData().getData()); + RuleEngineOriginatedNotificationInfo notificationInfo = RuleEngineOriginatedNotificationInfo.builder() + .msgOriginator(msg.getOriginator()) + .msgMetadata(msg.getMetaData().getData()) + .msgType(msg.getType()) + .build(); NotificationRequest notificationRequest = NotificationRequest.builder() .tenantId(ctx.getTenantId())