Merge pull request #8440 from thingsboard/improvements/notification-system
Improvements for notification system
This commit is contained in:
		
						commit
						d03f236263
					
				@ -16,6 +16,7 @@
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import io.swagger.annotations.ApiParam;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
@ -76,6 +77,16 @@ import java.util.Set;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_START;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
 | 
			
		||||
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@ -93,7 +104,10 @@ public class NotificationController extends BaseController {
 | 
			
		||||
    private final NotificationSettingsService notificationSettingsService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notifications (getNotifications)",
 | 
			
		||||
            notes = "**WebSocket API**:\n\n" +
 | 
			
		||||
            notes = "Returns the page of notifications for current user." + NEW_LINE +
 | 
			
		||||
                    PAGE_DATA_PARAMETERS +
 | 
			
		||||
                    AVAILABLE_FOR_ANY_AUTHORIZED_USER + NEW_LINE +
 | 
			
		||||
                    "**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" +
 | 
			
		||||
@ -144,11 +158,17 @@ public class NotificationController extends BaseController {
 | 
			
		||||
                    "}\n```")
 | 
			
		||||
    @GetMapping("/notifications")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    public PageData<Notification> getNotifications(@RequestParam int pageSize,
 | 
			
		||||
    public PageData<Notification> getNotifications(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                   @RequestParam int pageSize,
 | 
			
		||||
                                                   @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                   @RequestParam int page,
 | 
			
		||||
                                                   @ApiParam(value = "Case-insensitive 'substring' filter based on notification subject or text")
 | 
			
		||||
                                                   @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                   @ApiParam(value = SORT_PROPERTY_DESCRIPTION)
 | 
			
		||||
                                                   @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                   @ApiParam(value = SORT_ORDER_DESCRIPTION)
 | 
			
		||||
                                                   @RequestParam(required = false) String sortOrder,
 | 
			
		||||
                                                   @ApiParam(value = "To search for unread notifications only")
 | 
			
		||||
                                                   @RequestParam(defaultValue = "false") boolean unreadOnly,
 | 
			
		||||
                                                   @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        // no permissions
 | 
			
		||||
@ -156,6 +176,9 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return notificationService.findNotificationsByRecipientIdAndReadStatus(user.getTenantId(), user.getId(), unreadOnly, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Mark notification as read (markNotificationAsRead)",
 | 
			
		||||
            notes = "Marks notification as read by its id." +
 | 
			
		||||
                    AVAILABLE_FOR_ANY_AUTHORIZED_USER)
 | 
			
		||||
    @PutMapping("/notification/{id}/read")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    public void markNotificationAsRead(@PathVariable UUID id,
 | 
			
		||||
@ -165,6 +188,9 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        notificationCenter.markNotificationAsRead(user.getTenantId(), user.getId(), notificationId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Mark all notifications as read (markAllNotificationsAsRead)",
 | 
			
		||||
            notes = "Marks all unread notifications as read." +
 | 
			
		||||
                    AVAILABLE_FOR_ANY_AUTHORIZED_USER)
 | 
			
		||||
    @PutMapping("/notifications/read")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    public void markAllNotificationsAsRead(@AuthenticationPrincipal SecurityUser user) {
 | 
			
		||||
@ -172,6 +198,9 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        notificationCenter.markAllNotificationsAsRead(user.getTenantId(), user.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Delete notification (deleteNotification)",
 | 
			
		||||
            notes = "Deletes notification by its id." +
 | 
			
		||||
                    AVAILABLE_FOR_ANY_AUTHORIZED_USER)
 | 
			
		||||
    @DeleteMapping("/notification/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    public void deleteNotification(@PathVariable UUID id,
 | 
			
		||||
@ -181,6 +210,35 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        notificationCenter.deleteNotification(user.getTenantId(), user.getId(), notificationId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Create notification request (createNotificationRequest)",
 | 
			
		||||
            notes = "Processes notification request.\n" +
 | 
			
		||||
                    "Mandatory request properties are `targets` (list of targets ids to send notification to), " +
 | 
			
		||||
                    "and either `templateId` (existing notification template id) or `template` (to send notification without saving the template).\n" +
 | 
			
		||||
                    "Optionally, you can set `sendingDelayInSec` inside the `additionalConfig` field to schedule the notification." + NEW_LINE +
 | 
			
		||||
                    "For each enabled delivery method in the notification template, there must be a target in the `targets` list that supports this delivery method: " +
 | 
			
		||||
                    "if you chose `WEB`, `EMAIL` or `SMS` - there must be at least one target in `targets` of `PLATFORM_USERS` type.\n" +
 | 
			
		||||
                    "For `SLACK` delivery method - you need to chose at least one `SLACK` notification target." + NEW_LINE +
 | 
			
		||||
                    "Notification request object with `PROCESSING` status will be returned immediately, " +
 | 
			
		||||
                    "and the notification sending itself is done asynchronously. After all notifications are sent, " +
 | 
			
		||||
                    "the `status` of the request becomes `SENT`. Use `getNotificationRequestById` to see " +
 | 
			
		||||
                    "the notification request processing status and some sending stats. " + NEW_LINE +
 | 
			
		||||
                    "Here is an example of notification request to one target using saved template:\n" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_START +
 | 
			
		||||
                    "{\n" +
 | 
			
		||||
                    "  \"templateId\": {\n" +
 | 
			
		||||
                    "    \"entityType\": \"NOTIFICATION_TEMPLATE\",\n" +
 | 
			
		||||
                    "    \"id\": \"6dbc3670-e4dd-11ed-9401-dbcc5dff78be\"\n" +
 | 
			
		||||
                    "  },\n" +
 | 
			
		||||
                    "  \"targets\": [\n" +
 | 
			
		||||
                    "    \"320e3ed0-d785-11ed-a06c-21dd57dd88ca\"\n" +
 | 
			
		||||
                    "  ],\n" +
 | 
			
		||||
                    "  \"additionalConfig\": {\n" +
 | 
			
		||||
                    "    \"sendingDelayInSec\": 0\n" +
 | 
			
		||||
                    "  }\n" +
 | 
			
		||||
                    "}" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_END +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH
 | 
			
		||||
    )
 | 
			
		||||
    @PostMapping("/notification/request")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationRequest createNotificationRequest(@RequestBody @Valid NotificationRequest notificationRequest,
 | 
			
		||||
@ -200,9 +258,15 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return doSaveAndLog(EntityType.NOTIFICATION_REQUEST, notificationRequest, (tenantId, request) -> notificationCenter.processNotificationRequest(tenantId, request, null));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification request preview (getNotificationRequestPreview)",
 | 
			
		||||
            notes = "Returns preview for notification request." + NEW_LINE +
 | 
			
		||||
                    "`processedTemplates` shows how the notifications for each delivery method will look like " +
 | 
			
		||||
                    "for the first recipient of the corresponding notification target." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PostMapping("/notification/request/preview")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request,
 | 
			
		||||
                                                                    @ApiParam(value = "Amount of the recipients to show in preview")
 | 
			
		||||
                                                                    @RequestParam(defaultValue = "20") int recipientsPreviewSize,
 | 
			
		||||
                                                                    @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        NotificationTemplate template;
 | 
			
		||||
@ -281,6 +345,9 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return preview;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification request by id (getNotificationRequestById)",
 | 
			
		||||
            notes = "Fetches notification request info by request id." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/notification/request/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationRequestInfo getNotificationRequestById(@PathVariable UUID id) throws ThingsboardException {
 | 
			
		||||
@ -288,12 +355,21 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return checkEntityId(notificationRequestId, notificationRequestService::findNotificationRequestInfoById, Operation.READ);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification requests (getNotificationRequests)",
 | 
			
		||||
            notes = "Returns the page of notification requests submitted by users of this tenant or sysadmins." + NEW_LINE +
 | 
			
		||||
                    PAGE_DATA_PARAMETERS +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/notification/requests")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public PageData<NotificationRequestInfo> getNotificationRequests(@RequestParam int pageSize,
 | 
			
		||||
    public PageData<NotificationRequestInfo> getNotificationRequests(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                                     @RequestParam int pageSize,
 | 
			
		||||
                                                                     @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                                     @RequestParam int page,
 | 
			
		||||
                                                                     @ApiParam(value = "Case-insensitive 'substring' filed based on the used template name")
 | 
			
		||||
                                                                     @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                                     @ApiParam(value = SORT_PROPERTY_DESCRIPTION)
 | 
			
		||||
                                                                     @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                                     @ApiParam(value = SORT_ORDER_DESCRIPTION)
 | 
			
		||||
                                                                     @RequestParam(required = false) String sortOrder,
 | 
			
		||||
                                                                     @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        // generic permission
 | 
			
		||||
@ -301,6 +377,11 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return notificationRequestService.findNotificationRequestsInfosByTenantIdAndOriginatorType(user.getTenantId(), EntityType.USER, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Delete notification request (deleteNotificationRequest)",
 | 
			
		||||
            notes = "Deletes notification request by its id." + NEW_LINE +
 | 
			
		||||
                    "If the request has status `SENT` - all sent notifications for this request will be deleted. " +
 | 
			
		||||
                    "If it is `SCHEDULED`, the request will be cancelled." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @DeleteMapping("/notification/request/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public void deleteNotificationRequest(@PathVariable UUID id) throws Exception {
 | 
			
		||||
@ -310,6 +391,21 @@ public class NotificationController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Save notification settings (saveNotificationSettings)",
 | 
			
		||||
            notes = "Saves notification settings for this tenant or sysadmin.\n" +
 | 
			
		||||
                    "`deliveryMethodsConfigs` of the settings must be specified." + NEW_LINE +
 | 
			
		||||
                    "Here is an example of the notification settings with Slack configuration:\n" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_START +
 | 
			
		||||
                    "{\n" +
 | 
			
		||||
                    "  \"deliveryMethodsConfigs\": {\n" +
 | 
			
		||||
                    "    \"SLACK\": {\n" +
 | 
			
		||||
                    "      \"method\": \"SLACK\",\n" +
 | 
			
		||||
                    "      \"botToken\": \"xoxb-....\"\n" +
 | 
			
		||||
                    "    }\n" +
 | 
			
		||||
                    "  }\n" +
 | 
			
		||||
                    "}" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_END +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PostMapping("/notification/settings")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationSettings saveNotificationSettings(@RequestBody @Valid NotificationSettings notificationSettings,
 | 
			
		||||
@ -320,6 +416,9 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return notificationSettings;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification settings (getNotificationSettings)",
 | 
			
		||||
            notes = "Retrieves notification settings for this tenant or sysadmin." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/notification/settings")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationSettings getNotificationSettings(@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
@ -328,6 +427,9 @@ public class NotificationController extends BaseController {
 | 
			
		||||
        return notificationSettingsService.findNotificationSettings(tenantId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get available delivery methods (getAvailableDeliveryMethods)",
 | 
			
		||||
            notes = "Returns the list of delivery methods that are properly configured and are allowed to be used for sending notifications." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/notification/deliveryMethods")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public Set<NotificationDeliveryMethod> getAvailableDeliveryMethods(@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,8 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import io.swagger.annotations.ApiParam;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
@ -44,6 +46,15 @@ import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_START;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
 | 
			
		||||
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@ -55,6 +66,53 @@ public class NotificationRuleController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final NotificationRuleService notificationRuleService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Save notification rule (saveNotificationRule)",
 | 
			
		||||
            notes = "Creates or updates notification rule. " + NEW_LINE +
 | 
			
		||||
                    "Mandatory properties are `name`, `templateId` (of a template with `notificationType` matching to rule's `triggerType`), " +
 | 
			
		||||
                    "`triggerType`, `triggerConfig` and `recipientConfig`. Additionally, you may specify rule `description` " +
 | 
			
		||||
                    "inside of `additionalConfig`." + NEW_LINE +
 | 
			
		||||
                    "Trigger type of the rule cannot be changed. " +
 | 
			
		||||
                    "Available trigger types for tenant: `ENTITY_ACTION`, `ALARM`, `ALARM_COMMENT`, `ALARM_ASSIGNMENT`, " +
 | 
			
		||||
                    "`DEVICE_ACTIVITY`, `RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT`.\n" +
 | 
			
		||||
                    "For sysadmin, there are following trigger types available: `ENTITIES_LIMIT`, `API_USAGE_LIMIT`, " +
 | 
			
		||||
                    "`NEW_PLATFORM_VERSION`." + NEW_LINE +
 | 
			
		||||
                    "Here is an example of notification rule to send notification when a " +
 | 
			
		||||
                    "device, asset or customer is created or deleted:\n" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_START +
 | 
			
		||||
                    "{\n" +
 | 
			
		||||
                    "  \"name\": \"Entity action\",\n" +
 | 
			
		||||
                    "  \"templateId\": {\n" +
 | 
			
		||||
                    "    \"entityType\": \"NOTIFICATION_TEMPLATE\",\n" +
 | 
			
		||||
                    "    \"id\": \"32117320-d785-11ed-a06c-21dd57dd88ca\"\n" +
 | 
			
		||||
                    "  },\n" +
 | 
			
		||||
                    "  \"triggerType\": \"ENTITY_ACTION\",\n" +
 | 
			
		||||
                    "  \"triggerConfig\": {\n" +
 | 
			
		||||
                    "    \"entityTypes\": [\n" +
 | 
			
		||||
                    "      \"CUSTOMER\",\n" +
 | 
			
		||||
                    "      \"DEVICE\",\n" +
 | 
			
		||||
                    "      \"ASSET\"\n" +
 | 
			
		||||
                    "    ],\n" +
 | 
			
		||||
                    "    \"created\": true,\n" +
 | 
			
		||||
                    "    \"updated\": false,\n" +
 | 
			
		||||
                    "    \"deleted\": true,\n" +
 | 
			
		||||
                    "    \"triggerType\": \"ENTITY_ACTION\"\n" +
 | 
			
		||||
                    "  },\n" +
 | 
			
		||||
                    "  \"recipientsConfig\": {\n" +
 | 
			
		||||
                    "    \"targets\": [\n" +
 | 
			
		||||
                    "      \"320f2930-d785-11ed-a06c-21dd57dd88ca\"\n" +
 | 
			
		||||
                    "    ],\n" +
 | 
			
		||||
                    "    \"triggerType\": \"ENTITY_ACTION\"\n" +
 | 
			
		||||
                    "  },\n" +
 | 
			
		||||
                    "  \"additionalConfig\": {\n" +
 | 
			
		||||
                    "    \"description\": \"Send notification to tenant admins or customer users when a device, asset or customer is created\"\n" +
 | 
			
		||||
                    "  },\n" +
 | 
			
		||||
                    "  \"templateName\": \"Entity action notification\",\n" +
 | 
			
		||||
                    "  \"deliveryMethods\": [\n" +
 | 
			
		||||
                    "    \"WEB\"\n" +
 | 
			
		||||
                    "  ]\n" +
 | 
			
		||||
                    "}" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_END +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PostMapping("/rule")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationRule saveNotificationRule(@RequestBody @Valid NotificationRule notificationRule,
 | 
			
		||||
@ -74,6 +132,11 @@ public class NotificationRuleController extends BaseController {
 | 
			
		||||
        return notificationRule;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification rule by id (getNotificationRuleById)",
 | 
			
		||||
            notes = "Fetches notification rule info by rule's id.\n" +
 | 
			
		||||
                    "In addition to regular notification rule fields, " +
 | 
			
		||||
                    "there are `templateName` and `deliveryMethods` in the response." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/rule/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public NotificationRuleInfo getNotificationRuleById(@PathVariable UUID id) throws ThingsboardException {
 | 
			
		||||
@ -81,12 +144,21 @@ public class NotificationRuleController extends BaseController {
 | 
			
		||||
        return checkEntityId(notificationRuleId, notificationRuleService::findNotificationRuleInfoById, Operation.READ);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification rules (getNotificationRules)",
 | 
			
		||||
            notes = "Returns the page of notification rules." + NEW_LINE +
 | 
			
		||||
                    PAGE_DATA_PARAMETERS +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/rules")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public PageData<NotificationRuleInfo> getNotificationRules(@RequestParam int pageSize,
 | 
			
		||||
    public PageData<NotificationRuleInfo> getNotificationRules(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                               @RequestParam int pageSize,
 | 
			
		||||
                                                               @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                               @RequestParam int page,
 | 
			
		||||
                                                               @ApiParam(value = "Case-insensitive 'substring' filter based on rule's name")
 | 
			
		||||
                                                               @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                               @ApiParam(value = SORT_PROPERTY_DESCRIPTION)
 | 
			
		||||
                                                               @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                               @ApiParam(value = SORT_ORDER_DESCRIPTION)
 | 
			
		||||
                                                               @RequestParam(required = false) String sortOrder,
 | 
			
		||||
                                                               @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        // generic permission
 | 
			
		||||
@ -94,6 +166,10 @@ public class NotificationRuleController extends BaseController {
 | 
			
		||||
        return notificationRuleService.findNotificationRulesInfosByTenantId(user.getTenantId(), pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Delete notification rule (deleteNotificationRule)",
 | 
			
		||||
            notes = "Deletes notification rule by id.\n" +
 | 
			
		||||
                    "Cancels all related scheduled notification requests (e.g. due to escalation table)" +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @DeleteMapping("/rule/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public void deleteNotificationRule(@PathVariable UUID id,
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import io.swagger.annotations.ApiParam;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.apache.commons.collections.CollectionUtils;
 | 
			
		||||
@ -58,6 +59,14 @@ import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_START;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
 | 
			
		||||
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
 | 
			
		||||
 | 
			
		||||
@ -71,7 +80,28 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
    private final NotificationTargetService notificationTargetService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Save notification target (saveNotificationTarget)",
 | 
			
		||||
            notes = "Create or update notification target." +
 | 
			
		||||
            notes = "Creates or updates notification target." + NEW_LINE +
 | 
			
		||||
                    "Available `configuration` types are `PLATFORM_USERS` and `SLACK`.\n" +
 | 
			
		||||
                    "For `PLATFORM_USERS` the `usersFilter` must be specified. " +
 | 
			
		||||
                    "For tenant, there are following users filter types available: " +
 | 
			
		||||
                    "`USER_LIST`, `CUSTOMER_USERS`, `TENANT_ADMINISTRATORS`, `ALL_USERS`, " +
 | 
			
		||||
                    "`ORIGINATOR_ENTITY_OWNER_USERS`, `AFFECTED_USER`.\n" +
 | 
			
		||||
                    "For sysadmin: `TENANT_ADMINISTRATORS`, `AFFECTED_TENANT_ADMINISTRATORS`, " +
 | 
			
		||||
                    "`SYSTEM_ADMINISTRATORS`, `ALL_USERS`." + NEW_LINE +
 | 
			
		||||
                    "Here is an example of tenant-level notification target to send notification to customer's users:\n" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_START +
 | 
			
		||||
                    "{\n" +
 | 
			
		||||
                    "  \"name\": \"Users of Customer A\",\n" +
 | 
			
		||||
                    "  \"configuration\": {\n" +
 | 
			
		||||
                    "    \"type\": \"PLATFORM_USERS\",\n" +
 | 
			
		||||
                    "    \"usersFilter\": {\n" +
 | 
			
		||||
                    "      \"type\": \"CUSTOMER_USERS\",\n" +
 | 
			
		||||
                    "      \"customerId\": \"32499a20-d785-11ed-a06c-21dd57dd88ca\"\n" +
 | 
			
		||||
                    "    },\n" +
 | 
			
		||||
                    "    \"description\": \"Users of Customer A\"\n" +
 | 
			
		||||
                    "  }\n" +
 | 
			
		||||
                    "}" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_END +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PostMapping("/target")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
@ -89,7 +119,7 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification target by id (getNotificationTargetById)",
 | 
			
		||||
            notes = "Fetch saved notification target by id." +
 | 
			
		||||
            notes = "Fetches notification target by id." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/target/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
@ -99,12 +129,14 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get recipients for notification target config (getRecipientsForNotificationTargetConfig)",
 | 
			
		||||
            notes = "Get the list (page) of recipients (users) for such notification target configuration." +
 | 
			
		||||
            notes = "Returns the page of recipients for such notification target configuration." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PostMapping("/target/recipients")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public PageData<User> getRecipientsForNotificationTargetConfig(@RequestBody NotificationTarget notificationTarget,
 | 
			
		||||
                                                                   @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                                   @RequestParam int pageSize,
 | 
			
		||||
                                                                   @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                                   @RequestParam int page,
 | 
			
		||||
                                                                   @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        // generic permission
 | 
			
		||||
@ -119,9 +151,13 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
        return notificationTargetService.findRecipientsForNotificationTargetConfig(user.getTenantId(), (PlatformUsersNotificationTargetConfig) notificationTarget.getConfiguration(), pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification targets by ids (getNotificationTargetsByIds)",
 | 
			
		||||
            notes = "Returns the list of notification targets found by provided ids." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping(value = "/targets", params = {"ids"})
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public List<NotificationTarget> getNotificationTargetsByIds(@RequestParam("ids") UUID[] ids,
 | 
			
		||||
    public List<NotificationTarget> getNotificationTargetsByIds(@ApiParam(value = "Comma-separated list of uuids representing targets ids", required = true)
 | 
			
		||||
                                                                @RequestParam("ids") UUID[] ids,
 | 
			
		||||
                                                                @AuthenticationPrincipal SecurityUser user) {
 | 
			
		||||
        // generic permission
 | 
			
		||||
        List<NotificationTargetId> targetsIds = Arrays.stream(ids).map(NotificationTargetId::new).collect(Collectors.toList());
 | 
			
		||||
@ -129,14 +165,20 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification targets (getNotificationTargets)",
 | 
			
		||||
            notes = "Fetch the page of notification targets owned by sysadmin or tenant." +
 | 
			
		||||
            notes = "Returns the page of notification targets owned by sysadmin or tenant." + NEW_LINE +
 | 
			
		||||
                    PAGE_DATA_PARAMETERS +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/targets")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public PageData<NotificationTarget> getNotificationTargets(@RequestParam int pageSize,
 | 
			
		||||
    public PageData<NotificationTarget> getNotificationTargets(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                               @RequestParam int pageSize,
 | 
			
		||||
                                                               @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                               @RequestParam int page,
 | 
			
		||||
                                                               @ApiParam(value = "Case-insensitive 'substring' filed based on the target's name")
 | 
			
		||||
                                                               @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                               @ApiParam(value = SORT_PROPERTY_DESCRIPTION)
 | 
			
		||||
                                                               @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                               @ApiParam(value = SORT_ORDER_DESCRIPTION)
 | 
			
		||||
                                                               @RequestParam(required = false) String sortOrder,
 | 
			
		||||
                                                               @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        // generic permission
 | 
			
		||||
@ -144,6 +186,10 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
        return notificationTargetService.findNotificationTargetsByTenantId(user.getTenantId(), pageLink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification targets by supported notification type (getNotificationTargetsBySupportedNotificationType)",
 | 
			
		||||
            notes = "Returns the page of notification targets filtered by notification type that they can be used for." + NEW_LINE +
 | 
			
		||||
                    PAGE_DATA_PARAMETERS +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping(value = "/targets", params = "notificationType")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public PageData<NotificationTarget> getNotificationTargetsBySupportedNotificationType(@RequestParam int pageSize,
 | 
			
		||||
@ -158,7 +204,7 @@ public class NotificationTargetController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Delete notification target by id (deleteNotificationTargetById)",
 | 
			
		||||
            notes = "Delete notification target by its id.\n\n" +
 | 
			
		||||
            notes = "Deletes notification target by its id." + NEW_LINE +
 | 
			
		||||
                    "This target cannot be referenced by existing scheduled notification requests or any notification rules." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @DeleteMapping("/target/{id}")
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import io.swagger.annotations.ApiParam;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
@ -36,9 +37,9 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho
 | 
			
		||||
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.targets.slack.SlackConversation;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.targets.slack.SlackConversationType;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.targets.slack.SlackConversation;
 | 
			
		||||
import org.thingsboard.server.common.data.page.PageData;
 | 
			
		||||
import org.thingsboard.server.common.data.page.PageLink;
 | 
			
		||||
import org.thingsboard.server.dao.notification.NotificationSettingsService;
 | 
			
		||||
@ -51,6 +52,14 @@ import javax.validation.Valid;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_START;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
 | 
			
		||||
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
 | 
			
		||||
 | 
			
		||||
@ -65,19 +74,44 @@ public class NotificationTemplateController extends BaseController {
 | 
			
		||||
    private final SlackService slackService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Save notification template (saveNotificationTemplate)",
 | 
			
		||||
            notes = "Create or update notification template.\n\n" +
 | 
			
		||||
                    "Example:\n" +
 | 
			
		||||
                    "```\n{\n  \"name\": \"Hello to all my users\",\n" +
 | 
			
		||||
                    "  \"notificationType\": \"Message from administrator\",\n" +
 | 
			
		||||
            notes = "Creates or updates notification template." + NEW_LINE +
 | 
			
		||||
                    "Here is an example of template to send notification via Web, SMS and Slack:\n" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_START +
 | 
			
		||||
                    "{\n" +
 | 
			
		||||
                    "  \"name\": \"Greetings\",\n" +
 | 
			
		||||
                    "  \"notificationType\": \"GENERAL\",\n" +
 | 
			
		||||
                    "  \"configuration\": {\n" +
 | 
			
		||||
                    "    \"defaultTextTemplate\": \"Hello everyone\",  # required if any of the templates' bodies is not set\n" +
 | 
			
		||||
                    "    \"templates\": {\n" +
 | 
			
		||||
                    "      \"PUSH\": {\n        \"method\": \"PUSH\",\n        \"body\": null  # defaultTextTemplate will be used if body is not set\n      },\n" +
 | 
			
		||||
                    "      \"SMS\": {\n        \"method\": \"SMS\",\n        \"body\": null\n      },\n" +
 | 
			
		||||
                    "      \"EMAIL\": {\n        \"method\": \"EMAIL\",\n        \"body\": \"Non-default value for email notification: <body>Hello everyone</body>\",\n        \"subject\": \"Message from administrator\"\n      },\n" +
 | 
			
		||||
                    "      \"SLACK\": {\n        \"method\": \"SLACK\",\n        \"body\": null,\n        \"conversationType\": \"PUBLIC_CHANNEL\",\n        \"conversationId\": \"U02LD7BJOU2\"  # received from listSlackConversations API method\n      }\n" +
 | 
			
		||||
                    "    \"deliveryMethodsTemplates\": {\n" +
 | 
			
		||||
                    "      \"WEB\": {\n" +
 | 
			
		||||
                    "        \"enabled\": true,\n" +
 | 
			
		||||
                    "        \"subject\": \"Greetings\",\n" +
 | 
			
		||||
                    "        \"body\": \"Hi there, ${recipientTitle}\",\n" +
 | 
			
		||||
                    "        \"additionalConfig\": {\n" +
 | 
			
		||||
                    "          \"icon\": {\n" +
 | 
			
		||||
                    "            \"enabled\": true,\n" +
 | 
			
		||||
                    "            \"icon\": \"back_hand\",\n" +
 | 
			
		||||
                    "            \"color\": \"#757575\"\n" +
 | 
			
		||||
                    "          },\n" +
 | 
			
		||||
                    "          \"actionButtonConfig\": {\n" +
 | 
			
		||||
                    "            \"enabled\": false\n" +
 | 
			
		||||
                    "          }\n" +
 | 
			
		||||
                    "        },\n" +
 | 
			
		||||
                    "        \"method\": \"WEB\"\n" +
 | 
			
		||||
                    "      },\n" +
 | 
			
		||||
                    "      \"SMS\": {\n" +
 | 
			
		||||
                    "        \"enabled\": true,\n" +
 | 
			
		||||
                    "        \"body\": \"Hi there, ${recipientTitle}\",\n" +
 | 
			
		||||
                    "        \"method\": \"SMS\"\n" +
 | 
			
		||||
                    "      },\n" +
 | 
			
		||||
                    "      \"SLACK\": {\n" +
 | 
			
		||||
                    "        \"enabled\": true,\n" +
 | 
			
		||||
                    "        \"body\": \"Hi there, @${recipientTitle}\",\n" +
 | 
			
		||||
                    "        \"method\": \"SLACK\"\n" +
 | 
			
		||||
                    "      }\n" +
 | 
			
		||||
                    "    }\n" +
 | 
			
		||||
                    "  }\n}\n```" +
 | 
			
		||||
                    "  }\n" +
 | 
			
		||||
                    "}" +
 | 
			
		||||
                    MARKDOWN_CODE_BLOCK_END +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @PostMapping("/template")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
@ -88,7 +122,7 @@ public class NotificationTemplateController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification template by id (getNotificationTemplateById)",
 | 
			
		||||
            notes = "Fetch notification template by id." +
 | 
			
		||||
            notes = "Fetches notification template by id." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/template/{id}")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
@ -98,15 +132,22 @@ public class NotificationTemplateController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get notification templates (getNotificationTemplates)",
 | 
			
		||||
            notes = "Fetch the page of notification templates owned by sysadmin or tenant." +
 | 
			
		||||
            notes = "Returns the page of notification templates owned by sysadmin or tenant." + NEW_LINE +
 | 
			
		||||
                    PAGE_DATA_PARAMETERS +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/templates")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public PageData<NotificationTemplate> getNotificationTemplates(@RequestParam int pageSize,
 | 
			
		||||
    public PageData<NotificationTemplate> getNotificationTemplates(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                                   @RequestParam int pageSize,
 | 
			
		||||
                                                                   @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                                   @RequestParam int page,
 | 
			
		||||
                                                                   @ApiParam(value = "Case-insensitive 'substring' filter based on template's name and notification type")
 | 
			
		||||
                                                                   @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                                   @ApiParam(value = SORT_PROPERTY_DESCRIPTION)
 | 
			
		||||
                                                                   @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                                   @ApiParam(value = SORT_ORDER_DESCRIPTION)
 | 
			
		||||
                                                                   @RequestParam(required = false) String sortOrder,
 | 
			
		||||
                                                                   @ApiParam(value = "Comma-separated list of notification types to filter the templates")
 | 
			
		||||
                                                                   @RequestParam(required = false) NotificationType[] notificationTypes,
 | 
			
		||||
                                                                   @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
 | 
			
		||||
        // generic permission
 | 
			
		||||
@ -119,7 +160,7 @@ public class NotificationTemplateController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Delete notification template by id (deleteNotificationTemplateById",
 | 
			
		||||
            notes = "Delete notification template by its id.\n\n" +
 | 
			
		||||
            notes = "Deletes notification template by its id." + NEW_LINE +
 | 
			
		||||
                    "This template cannot be referenced by existing scheduled notification requests or any notification rules." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @DeleteMapping("/template/{id}")
 | 
			
		||||
@ -131,12 +172,12 @@ public class NotificationTemplateController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "List Slack conversations (listSlackConversations)",
 | 
			
		||||
            notes = "List available Slack conversations by type to use in notification template.\n\n" +
 | 
			
		||||
                    "Slack must be configured in notification settings." +
 | 
			
		||||
            notes = "List available Slack conversations by type." +
 | 
			
		||||
                    SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
 | 
			
		||||
    @GetMapping("/slack/conversations")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
 | 
			
		||||
    public List<SlackConversation> listSlackConversations(@RequestParam SlackConversationType type,
 | 
			
		||||
                                                          @ApiParam(value = "Slack bot token. If absent - system Slack settings will be used")
 | 
			
		||||
                                                          @RequestParam(required = false) String token,
 | 
			
		||||
                                                          @AuthenticationPrincipal SecurityUser user) {
 | 
			
		||||
        // generic permission
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,6 @@ import org.thingsboard.server.common.data.notification.NotificationRequestConfig
 | 
			
		||||
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.NotificationStatus;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.NotificationType;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
 | 
			
		||||
import org.thingsboard.server.common.data.notification.targets.NotificationRecipient;
 | 
			
		||||
@ -294,24 +293,6 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
 | 
			
		||||
        return onNotificationUpdate(recipient.getTenantId(), recipient.getId(), update);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void sendBasicNotification(TenantId tenantId, UserId recipientId, String subject, String text) {
 | 
			
		||||
        Notification notification = Notification.builder()
 | 
			
		||||
                .recipientId(recipientId)
 | 
			
		||||
                .type(NotificationType.GENERAL)
 | 
			
		||||
                .subject(subject)
 | 
			
		||||
                .text(text)
 | 
			
		||||
                .status(NotificationStatus.SENT)
 | 
			
		||||
                .build();
 | 
			
		||||
        notification = notificationService.saveNotification(TenantId.SYS_TENANT_ID, notification);
 | 
			
		||||
 | 
			
		||||
        NotificationUpdate update = NotificationUpdate.builder()
 | 
			
		||||
                .created(true)
 | 
			
		||||
                .notification(notification)
 | 
			
		||||
                .build();
 | 
			
		||||
        onNotificationUpdate(tenantId, recipientId, update);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void markNotificationAsRead(TenantId tenantId, UserId recipientId, NotificationId notificationId) {
 | 
			
		||||
        boolean updated = notificationService.markNotificationAsRead(tenantId, recipientId, notificationId);
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,6 @@ public class NotificationRequest extends BaseData<NotificationRequestId> impleme
 | 
			
		||||
    private NotificationTemplate template;
 | 
			
		||||
    @Valid
 | 
			
		||||
    private NotificationInfo info;
 | 
			
		||||
    @NotNull
 | 
			
		||||
    @Valid
 | 
			
		||||
    private NotificationRequestConfig additionalConfig;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -20,12 +20,12 @@ import lombok.Getter;
 | 
			
		||||
@Getter
 | 
			
		||||
public enum NotificationRuleTriggerType {
 | 
			
		||||
 | 
			
		||||
    ENTITY_ACTION,
 | 
			
		||||
    ALARM,
 | 
			
		||||
    ALARM_COMMENT,
 | 
			
		||||
    DEVICE_ACTIVITY,
 | 
			
		||||
    ENTITY_ACTION,
 | 
			
		||||
    RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT,
 | 
			
		||||
    ALARM_ASSIGNMENT,
 | 
			
		||||
    DEVICE_ACTIVITY,
 | 
			
		||||
    RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT,
 | 
			
		||||
    NEW_PLATFORM_VERSION(false),
 | 
			
		||||
    ENTITIES_LIMIT(false),
 | 
			
		||||
    API_USAGE_LIMIT(false);
 | 
			
		||||
 | 
			
		||||
@ -109,7 +109,7 @@ public class DefaultNotificationSettingsService implements NotificationSettingsS
 | 
			
		||||
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.newAlarm, tenantAdmins.getId());
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.alarmUpdate, tenantAdmins.getId());
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.deviceAction, tenantAdmins.getId());
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.entityAction, tenantAdmins.getId());
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.deviceActivity, tenantAdmins.getId());
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.alarmComment, tenantAdmins.getId());
 | 
			
		||||
        defaultNotifications.create(tenantId, DefaultNotifications.alarmAssignment, affectedUser.getId());
 | 
			
		||||
 | 
			
		||||
@ -179,13 +179,13 @@ public class DefaultNotifications {
 | 
			
		||||
                    .description("Send notification to tenant admins when any alarm is updated or cleared")
 | 
			
		||||
                    .build())
 | 
			
		||||
            .build();
 | 
			
		||||
    public static final DefaultNotification deviceAction = DefaultNotification.builder()
 | 
			
		||||
            .name("Device action notification")
 | 
			
		||||
    public static final DefaultNotification entityAction = DefaultNotification.builder()
 | 
			
		||||
            .name("Entity action notification")
 | 
			
		||||
            .type(NotificationType.ENTITY_ACTION)
 | 
			
		||||
            .subject("${entityType} was ${actionType}")
 | 
			
		||||
            .text("${entityType} '${entityName}' was ${actionType} by user ${userEmail}")
 | 
			
		||||
            .icon("info").color(null)
 | 
			
		||||
            .button("Go to device").link("/devices/${entityId}")
 | 
			
		||||
            .button("Go to ${entityType:lowerCase}").link("/${entityType:lowerCase}s/${entityId}")
 | 
			
		||||
            .rule(DefaultRule.builder()
 | 
			
		||||
                    .name("Device created")
 | 
			
		||||
                    .triggerConfig(EntityActionNotificationRuleTriggerConfig.builder()
 | 
			
		||||
@ -341,7 +341,7 @@ public class DefaultNotifications {
 | 
			
		||||
        public NotificationRule toRule(NotificationTemplateId templateId, NotificationTargetId... targets) {
 | 
			
		||||
            DefaultRule defaultRule = this.rule;
 | 
			
		||||
            NotificationRule rule = new NotificationRule();
 | 
			
		||||
            rule.setName(name);
 | 
			
		||||
            rule.setName(defaultRule.getName());
 | 
			
		||||
            rule.setTemplateId(templateId);
 | 
			
		||||
            rule.setTriggerType(defaultRule.getTriggerConfig().getTriggerType());
 | 
			
		||||
            rule.setTriggerConfig(defaultRule.getTriggerConfig());
 | 
			
		||||
 | 
			
		||||
@ -32,8 +32,6 @@ public interface NotificationCenter {
 | 
			
		||||
 | 
			
		||||
    void deleteNotificationRequest(TenantId tenantId, NotificationRequestId notificationRequestId);
 | 
			
		||||
 | 
			
		||||
    void sendBasicNotification(TenantId tenantId, UserId recipientId, String subject, String text);
 | 
			
		||||
 | 
			
		||||
    void markNotificationAsRead(TenantId tenantId, UserId recipientId, NotificationId notificationId);
 | 
			
		||||
 | 
			
		||||
    void markAllNotificationsAsRead(TenantId tenantId, UserId recipientId);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user