Browse Source

Notification target and template api docs; improvements

pull/7925/head
ViacheslavKlimov 4 years ago
parent
commit
141bd74113
  1. 23
      application/src/main/java/org/thingsboard/server/controller/NotificationController.java
  2. 3
      application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java
  3. 32
      application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java
  4. 74
      application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java
  5. 20
      application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthConfigTest.java
  6. 7
      common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateService.java
  7. 2
      common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
  8. 10
      common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationId.java
  9. 1
      common/data/src/main/java/org/thingsboard/server/common/data/notification/template/SlackDeliveryMethodNotificationTemplate.java
  10. 8
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java
  11. 4
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/SmsTwoFaAccountConfig.java
  12. 4
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/TotpTwoFaAccountConfig.java
  13. 2
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/BackupCodeTwoFaProviderConfig.java
  14. 2
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/OtpBasedTwoFaProviderConfig.java
  15. 4
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/SmsTwoFaProviderConfig.java
  16. 2
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/TotpTwoFaProviderConfig.java
  17. 18
      dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java
  18. 7
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRuleService.java
  19. 7
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java
  20. 6
      dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java
  21. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java
  22. 4
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java
  23. 4
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRuleDao.java
  24. 4
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java
  25. 13
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java
  26. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java

23
application/src/main/java/org/thingsboard/server/controller/NotificationController.java

@ -29,19 +29,15 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.rule.engine.api.NotificationManager; import org.thingsboard.rule.engine.api.NotificationManager;
import org.thingsboard.server.common.data.notification.template.SlackConversation;
import org.thingsboard.rule.engine.api.slack.SlackService;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationOriginatorType; import org.thingsboard.server.common.data.notification.NotificationOriginatorType;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.notification.NotificationRequestService; import org.thingsboard.server.dao.notification.NotificationRequestService;
@ -52,7 +48,7 @@ import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import java.util.List; import javax.validation.Valid;
import java.util.UUID; import java.util.UUID;
@RestController @RestController
@ -66,7 +62,6 @@ public class NotificationController extends BaseController {
private final NotificationRequestService notificationRequestService; private final NotificationRequestService notificationRequestService;
private final NotificationManager notificationManager; private final NotificationManager notificationManager;
private final NotificationSettingsService notificationSettingsService; private final NotificationSettingsService notificationSettingsService;
private final SlackService slackService;
@GetMapping("/notifications") @GetMapping("/notifications")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@ -93,7 +88,7 @@ public class NotificationController extends BaseController {
@PostMapping("/notification/request") @PostMapping("/notification/request")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequest createNotificationRequest(@RequestBody NotificationRequest notificationRequest, public NotificationRequest createNotificationRequest(@RequestBody @Valid NotificationRequest notificationRequest,
@AuthenticationPrincipal SecurityUser user) throws Exception { @AuthenticationPrincipal SecurityUser user) throws Exception {
if (notificationRequest.getId() != null) { if (notificationRequest.getId() != null) {
throw new IllegalArgumentException("Notification request cannot be updated. You may only cancel/delete it"); throw new IllegalArgumentException("Notification request cannot be updated. You may only cancel/delete it");
@ -157,18 +152,4 @@ public class NotificationController extends BaseController {
return notificationSettingsService.findNotificationSettings(tenantId); return notificationSettingsService.findNotificationSettings(tenantId);
} }
@GetMapping("/notification/slack/conversations")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public List<SlackConversation> listSlackConversations(@RequestParam SlackConversation.Type type,
@AuthenticationPrincipal SecurityUser user) {
NotificationSettings settings = getNotificationSettings(user);
SlackNotificationDeliveryMethodConfig slackConfig = (SlackNotificationDeliveryMethodConfig)
settings.getDeliveryMethodsConfigs().get(NotificationDeliveryMethod.SLACK);
if (slackConfig == null) {
throw new IllegalArgumentException("Slack is not configured");
}
return slackService.listConversations(user.getTenantId(), slackConfig.getBotToken(), type);
}
} }

3
application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java

@ -40,6 +40,7 @@ import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import javax.validation.Valid;
import java.util.UUID; import java.util.UUID;
@RestController @RestController
@ -53,7 +54,7 @@ public class NotificationRuleController extends BaseController {
@PostMapping("/rule") @PostMapping("/rule")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
public NotificationRule saveNotificationRule(@RequestBody NotificationRule notificationRule) throws Exception { public NotificationRule saveNotificationRule(@RequestBody @Valid NotificationRule notificationRule) throws Exception {
checkEntity(notificationRule.getId(), notificationRule, Resource.NOTIFICATION_RULE); checkEntity(notificationRule.getId(), notificationRule, Resource.NOTIFICATION_RULE);
return doSaveAndLog(EntityType.NOTIFICATION_RULE, notificationRule, notificationRuleService::saveNotificationRule); return doSaveAndLog(EntityType.NOTIFICATION_RULE, notificationRule, notificationRuleService::saveNotificationRule);
} }

32
application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@ -45,6 +46,8 @@ import org.thingsboard.server.service.security.permission.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@RequestMapping("/api/notification") @RequestMapping("/api/notification")
@ -54,6 +57,20 @@ public class NotificationTargetController extends BaseController {
private final NotificationTargetService notificationTargetService; private final NotificationTargetService notificationTargetService;
@ApiOperation(value = "Save notification target (saveNotificationTarget)",
notes = "Create or update notification target.\n\n" +
"Examples with different configuration types:\n" +
"- SINGLE_USER:\n" +
"```\n{\n \"name\": \"Me\",\n \"configuration\": {\n \"type\": \"SINGLE_USER\",\n \"userId\": \"ea31a460-3d85-11ed-9200-77fc04fa14fa\"\n }\n}\n```\n" +
"- USER_LIST:\n" +
"```\n{\n \"name\": \"Special users\",\n \"configuration\": {\n \"type\": \"USER_LIST\",\n \"usersIds\": [\n \"ea31a460-3d85-11ed-9200-77fc04fa14fa\",\n \"86f7b260-3d88-11ed-ad72-ad2ee0f70ba1\"\n ]\n }\n}\n```\n" +
"- CUSTOMER_USERS (not accessible to system administrator):\n" +
"```\n{\n \"name\": \"Users of my customer\",\n \"configuration\": {\n \"type\": \"CUSTOMER_USERS\",\n \"customerId\": \"ea31a460-3d85-11ed-9200-77fc04fa14fa\"\n }\n}\n```\n" +
"or if you would like to use the target in notification rule and get customerId from alarm:\n" +
"```\n{\n \"name\": \"Alarm's customer users\",\n \"configuration\": {\n \"type\": \"CUSTOMER_USERS\",\n \"customerId\": null,\n \"getCustomerIdFromOriginatorEntity\": true\n }\n}\n```\n" +
"- ALL_USERS:\n" +
"```\n{\n \"name\": \"All my users\",\n \"configuration\": {\n \"type\": \"ALL_USERS\"\n }\n}\n```\n\n" +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@PostMapping("/target") @PostMapping("/target")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationTarget saveNotificationTarget(@RequestBody @Valid NotificationTarget notificationTarget, public NotificationTarget saveNotificationTarget(@RequestBody @Valid NotificationTarget notificationTarget,
@ -72,6 +89,9 @@ public class NotificationTargetController extends BaseController {
return doSaveAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::saveNotificationTarget); return doSaveAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::saveNotificationTarget);
} }
@ApiOperation(value = "Get notification target by id (getNotificationTargetById)",
notes = "Fetch saved notification target by id." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@GetMapping("/target/{id}") @GetMapping("/target/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationTarget getNotificationTargetById(@PathVariable UUID id) throws ThingsboardException { public NotificationTarget getNotificationTargetById(@PathVariable UUID id) throws ThingsboardException {
@ -79,6 +99,9 @@ public class NotificationTargetController extends BaseController {
return checkEntityId(notificationTargetId, notificationTargetService::findNotificationTargetById, Operation.READ); return checkEntityId(notificationTargetId, notificationTargetService::findNotificationTargetById, Operation.READ);
} }
@ApiOperation(value = "Get recipient for notification target config (getRecipientsForNotificationTargetConfig)",
notes = "Get the list (page) of recipients (users) for such notification target configuration." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@PostMapping("/target/recipients") @PostMapping("/target/recipients")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public PageData<User> getRecipientsForNotificationTargetConfig(@RequestBody NotificationTarget notificationTarget, public PageData<User> getRecipientsForNotificationTargetConfig(@RequestBody NotificationTarget notificationTarget,
@ -95,6 +118,9 @@ public class NotificationTargetController extends BaseController {
return recipients; return recipients;
} }
@ApiOperation(value = "Get notification targets (getNotificationTargets)",
notes = "Fetch the page of notification targets owned by sysadmin or tenant." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@GetMapping("/targets") @GetMapping("/targets")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public PageData<NotificationTarget> getNotificationTargets(@RequestParam int pageSize, public PageData<NotificationTarget> getNotificationTargets(@RequestParam int pageSize,
@ -107,9 +133,13 @@ public class NotificationTargetController extends BaseController {
return notificationTargetService.findNotificationTargetsByTenantId(user.getTenantId(), pageLink); return notificationTargetService.findNotificationTargetsByTenantId(user.getTenantId(), pageLink);
} }
@ApiOperation(value = "Delete notification target by id (deleteNotificationTargetById)",
notes = "Delete notification target by its id.\n\n" +
"This target cannot be referenced by existing scheduled notification requests or any notification rules." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@DeleteMapping("/target/{id}") @DeleteMapping("/target/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public void deleteNotificationTarget(@PathVariable UUID id) throws Exception { public void deleteNotificationTargetById(@PathVariable UUID id) throws Exception {
NotificationTargetId notificationTargetId = new NotificationTargetId(id); NotificationTargetId notificationTargetId = new NotificationTargetId(id);
NotificationTarget notificationTarget = checkEntityId(notificationTargetId, notificationTargetService::findNotificationTargetById, Operation.DELETE); NotificationTarget notificationTarget = checkEntityId(notificationTargetId, notificationTargetService::findNotificationTargetById, Operation.DELETE);
doDeleteAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::deleteNotificationTargetById); doDeleteAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::deleteNotificationTargetById);

74
application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java

@ -15,27 +15,42 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.rule.engine.api.slack.SlackService;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.NotificationTemplateId; import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
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; import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.SlackConversation;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.notification.NotificationSettingsService;
import org.thingsboard.server.dao.notification.NotificationTemplateService; import org.thingsboard.server.dao.notification.NotificationTemplateService;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@RequiredArgsConstructor @RequiredArgsConstructor
@ -43,7 +58,24 @@ import java.util.UUID;
public class NotificationTemplateController extends BaseController { public class NotificationTemplateController extends BaseController {
private final NotificationTemplateService notificationTemplateService; private final NotificationTemplateService notificationTemplateService;
private final NotificationSettingsService notificationSettingsService;
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" +
" \"configuration\": {\n" +
" \"defaultTextTemplate\": \"Hello everyone\", # required if any of the templates' bodies is not set\n" +
" \"templates\": {\n" +
" \"WEBSOCKET\": {\n \"method\": \"WEBSOCKET\",\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" +
" }\n" +
" }\n}\n```" +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@PostMapping("/template") @PostMapping("/template")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationTemplate saveNotificationTemplate(@RequestBody @Valid NotificationTemplate notificationTemplate) throws Exception { public NotificationTemplate saveNotificationTemplate(@RequestBody @Valid NotificationTemplate notificationTemplate) throws Exception {
@ -51,6 +83,9 @@ public class NotificationTemplateController extends BaseController {
return doSaveAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::saveNotificationTemplate); return doSaveAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::saveNotificationTemplate);
} }
@ApiOperation(value = "Get notification template by id (getNotificationTemplateById)",
notes = "Fetch notification template by id." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@GetMapping("/template/{id}") @GetMapping("/template/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationTemplate getNotificationTemplateById(@PathVariable UUID id) throws ThingsboardException { public NotificationTemplate getNotificationTemplateById(@PathVariable UUID id) throws ThingsboardException {
@ -58,12 +93,49 @@ public class NotificationTemplateController extends BaseController {
return checkEntityId(notificationTemplateId, notificationTemplateService::findNotificationTemplateById, Operation.READ); return checkEntityId(notificationTemplateId, notificationTemplateService::findNotificationTemplateById, Operation.READ);
} }
@ApiOperation(value = "Get notification templates (getNotificationTemplates)",
notes = "Fetch the page of notification templates owned by sysadmin or tenant." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@GetMapping("/templates")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public PageData<NotificationTemplate> getNotificationTemplates(@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationTemplateService.findNotificationTemplatesByTenantId(user.getTenantId(), pageLink);
}
@ApiOperation(value = "Delete notification template by id (deleteNotificationTemplateById",
notes = "Delete notification template by its id.\n\n" +
"This template cannot be referenced by existing scheduled notification requests or any notification rules." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@DeleteMapping("/template/{id}") @DeleteMapping("/template/{id}")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public void deleteNotificationTemplate(@PathVariable UUID id) throws Exception { public void deleteNotificationTemplateById(@PathVariable UUID id) throws Exception {
NotificationTemplateId notificationTemplateId = new NotificationTemplateId(id); NotificationTemplateId notificationTemplateId = new NotificationTemplateId(id);
NotificationTemplate notificationTemplate = checkEntityId(notificationTemplateId, notificationTemplateService::findNotificationTemplateById, Operation.DELETE); NotificationTemplate notificationTemplate = checkEntityId(notificationTemplateId, notificationTemplateService::findNotificationTemplateById, Operation.DELETE);
doDeleteAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::deleteNotificationTemplateById); doDeleteAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::deleteNotificationTemplateById);
} }
@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." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@GetMapping("/slack/conversations")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public List<SlackConversation> listSlackConversations(@RequestParam SlackConversation.Type type,
@AuthenticationPrincipal SecurityUser user) {
NotificationSettings settings = notificationSettingsService.findNotificationSettings(user.getTenantId());
SlackNotificationDeliveryMethodConfig slackConfig = (SlackNotificationDeliveryMethodConfig)
settings.getDeliveryMethodsConfigs().get(NotificationDeliveryMethod.SLACK);
if (slackConfig == null) {
throw new IllegalArgumentException("Slack is not configured");
}
return slackService.listConversations(user.getTenantId(), slackConfig.getBotToken(), type);
}
} }

20
application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthConfigTest.java

@ -124,9 +124,9 @@ public abstract class TwoFactorAuthConfigTest extends AbstractControllerTest {
.andExpect(status().isBadRequest())); .andExpect(status().isBadRequest()));
assertThat(errorMessage).contains( assertThat(errorMessage).contains(
"verification code check rate limit configuration is invalid", "verificationCodeCheckRateLimit is invalid",
"maximum number of verification failure before user lockout must be positive", "maxVerificationFailuresBeforeUserLockout must be positive",
"total amount of time allotted for verification must be greater than or equal 60" "totalAllowedTimeForVerification must be greater than or equal to 60"
); );
} }
@ -136,7 +136,7 @@ public abstract class TwoFactorAuthConfigTest extends AbstractControllerTest {
invalidTotpTwoFaProviderConfig.setIssuerName(" "); invalidTotpTwoFaProviderConfig.setIssuerName(" ");
String errorResponse = savePlatformTwoFaSettingsAndGetError(invalidTotpTwoFaProviderConfig); String errorResponse = savePlatformTwoFaSettingsAndGetError(invalidTotpTwoFaProviderConfig);
assertThat(errorResponse).containsIgnoringCase("issuer name must not be blank"); assertThat(errorResponse).containsIgnoringCase("issuerName must not be blank");
} }
@Test @Test
@ -151,8 +151,8 @@ public abstract class TwoFactorAuthConfigTest extends AbstractControllerTest {
invalidSmsTwoFaProviderConfig.setSmsVerificationMessageTemplate(null); invalidSmsTwoFaProviderConfig.setSmsVerificationMessageTemplate(null);
invalidSmsTwoFaProviderConfig.setVerificationCodeLifetime(0); invalidSmsTwoFaProviderConfig.setVerificationCodeLifetime(0);
errorResponse = savePlatformTwoFaSettingsAndGetError(invalidSmsTwoFaProviderConfig); errorResponse = savePlatformTwoFaSettingsAndGetError(invalidSmsTwoFaProviderConfig);
assertThat(errorResponse).containsIgnoringCase("verification message template is required"); assertThat(errorResponse).containsIgnoringCase("smsVerificationMessageTemplate is required");
assertThat(errorResponse).containsIgnoringCase("verification code lifetime is required"); assertThat(errorResponse).containsIgnoringCase("verificationCodeLifetime is required");
} }
private String savePlatformTwoFaSettingsAndGetError(TwoFaProviderConfig invalidTwoFaProviderConfig) throws Exception { private String savePlatformTwoFaSettingsAndGetError(TwoFaProviderConfig invalidTwoFaProviderConfig) throws Exception {
@ -216,12 +216,12 @@ public abstract class TwoFactorAuthConfigTest extends AbstractControllerTest {
String errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", totpTwoFaAccountConfig) String errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", totpTwoFaAccountConfig)
.andExpect(status().isBadRequest())); .andExpect(status().isBadRequest()));
assertThat(errorMessage).containsIgnoringCase("otp auth url cannot be blank"); assertThat(errorMessage).containsIgnoringCase("authUrl must not be blank");
totpTwoFaAccountConfig.setAuthUrl("otpauth://totp/T B: aba"); totpTwoFaAccountConfig.setAuthUrl("otpauth://totp/T B: aba");
errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", totpTwoFaAccountConfig) errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", totpTwoFaAccountConfig)
.andExpect(status().isBadRequest())); .andExpect(status().isBadRequest()));
assertThat(errorMessage).containsIgnoringCase("otp auth url is invalid"); assertThat(errorMessage).containsIgnoringCase("authUrl is invalid");
totpTwoFaAccountConfig.setAuthUrl("otpauth://totp/ThingsBoard%20(Tenant):tenant@thingsboard.org?issuer=ThingsBoard+%28Tenant%29&secret=FUNBIM3CXFNNGQR6ZIPVWHP65PPFWDII"); totpTwoFaAccountConfig.setAuthUrl("otpauth://totp/ThingsBoard%20(Tenant):tenant@thingsboard.org?issuer=ThingsBoard+%28Tenant%29&secret=FUNBIM3CXFNNGQR6ZIPVWHP65PPFWDII");
doPost("/api/2fa/account/config/submit", totpTwoFaAccountConfig) doPost("/api/2fa/account/config/submit", totpTwoFaAccountConfig)
@ -336,14 +336,14 @@ public abstract class TwoFactorAuthConfigTest extends AbstractControllerTest {
String errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", smsTwoFaAccountConfig) String errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", smsTwoFaAccountConfig)
.andExpect(status().isBadRequest())); .andExpect(status().isBadRequest()));
assertThat(errorMessage).containsIgnoringCase("phone number cannot be blank"); assertThat(errorMessage).containsIgnoringCase("phoneNumber must not be blank");
String nonE164PhoneNumber = "8754868"; String nonE164PhoneNumber = "8754868";
smsTwoFaAccountConfig.setPhoneNumber(nonE164PhoneNumber); smsTwoFaAccountConfig.setPhoneNumber(nonE164PhoneNumber);
errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", smsTwoFaAccountConfig) errorMessage = getErrorMessage(doPost("/api/2fa/account/config/submit", smsTwoFaAccountConfig)
.andExpect(status().isBadRequest())); .andExpect(status().isBadRequest()));
assertThat(errorMessage).containsIgnoringCase("phone number is not of E.164 format"); assertThat(errorMessage).containsIgnoringCase("phoneNumber is not of E.164 format");
} }
@Test @Test

7
common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateService.java

@ -17,10 +17,9 @@ package org.thingsboard.server.dao.notification;
import org.thingsboard.server.common.data.id.NotificationTemplateId; import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.page.PageData;
import java.util.List; import org.thingsboard.server.common.data.page.PageLink;
public interface NotificationTemplateService { public interface NotificationTemplateService {
@ -28,6 +27,8 @@ public interface NotificationTemplateService {
NotificationTemplate saveNotificationTemplate(TenantId tenantId, NotificationTemplate notificationTemplate); NotificationTemplate saveNotificationTemplate(TenantId tenantId, NotificationTemplate notificationTemplate);
PageData<NotificationTemplate> findNotificationTemplatesByTenantId(TenantId tenantId, PageLink pageLink);
void deleteNotificationTemplateById(TenantId tenantId, NotificationTemplateId id); void deleteNotificationTemplateById(TenantId tenantId, NotificationTemplateId id);
} }

2
common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java

@ -21,5 +21,5 @@ package org.thingsboard.server.common.data;
public enum EntityType { public enum EntityType {
TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE,
TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE, TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE,
NOTIFICATION_TARGET, NOTIFICATION_TEMPLATE, NOTIFICATION_REQUEST, NOTIFICATION_RULE; NOTIFICATION_TARGET, NOTIFICATION_TEMPLATE, NOTIFICATION_REQUEST, NOTIFICATION, NOTIFICATION_RULE;
} }

10
common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationId.java

@ -17,12 +17,20 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID; import java.util.UUID;
public class NotificationId extends UUIDBased { public class NotificationId extends UUIDBased implements EntityId {
@JsonCreator @JsonCreator
public NotificationId(@JsonProperty("id") UUID id) { public NotificationId(@JsonProperty("id") UUID id) {
super(id); super(id);
} }
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION;
}
} }

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

@ -23,7 +23,6 @@ import lombok.EqualsAndHashCode;
public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate { public class SlackDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate {
private SlackConversation.Type conversationType; private SlackConversation.Type conversationType;
// add Conversation type!
private String conversationId; // not required, set from user's name if not set private String conversationId; // not required, set from user's name if not set
} }

8
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java

@ -36,14 +36,14 @@ public class PlatformTwoFaSettings {
private List<TwoFaProviderConfig> providers; private List<TwoFaProviderConfig> providers;
@NotNull @NotNull
@Min(value = 5, message = "minimum verification code sent period must be greater than or equal 5") @Min(value = 5)
private Integer minVerificationCodeSendPeriod; private Integer minVerificationCodeSendPeriod;
@Pattern(regexp = "[1-9]\\d*:[1-9]\\d*", message = "verification code check rate limit configuration is invalid") @Pattern(regexp = "[1-9]\\d*:[1-9]\\d*", message = "is invalid")
private String verificationCodeCheckRateLimit; private String verificationCodeCheckRateLimit;
@Min(value = 0, message = "maximum number of verification failure before user lockout must be positive") @Min(value = 0, message = "must be positive")
private Integer maxVerificationFailuresBeforeUserLockout; private Integer maxVerificationFailuresBeforeUserLockout;
@NotNull @NotNull
@Min(value = 60, message = "total amount of time allotted for verification must be greater than or equal 60") @Min(value = 60)
private Integer totalAllowedTimeForVerification; private Integer totalAllowedTimeForVerification;

4
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/SmsTwoFaAccountConfig.java

@ -26,8 +26,8 @@ import javax.validation.constraints.Pattern;
@Data @Data
public class SmsTwoFaAccountConfig extends OtpBasedTwoFaAccountConfig { public class SmsTwoFaAccountConfig extends OtpBasedTwoFaAccountConfig {
@NotBlank(message = "phone number cannot be blank") @NotBlank
@Pattern(regexp = "^\\+[1-9]\\d{1,14}$", message = "phone number is not of E.164 format") @Pattern(regexp = "^\\+[1-9]\\d{1,14}$", message = "is not of E.164 format")
private String phoneNumber; private String phoneNumber;
@Override @Override

4
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/TotpTwoFaAccountConfig.java

@ -26,8 +26,8 @@ import javax.validation.constraints.Pattern;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class TotpTwoFaAccountConfig extends TwoFaAccountConfig { public class TotpTwoFaAccountConfig extends TwoFaAccountConfig {
@NotBlank(message = "OTP auth URL cannot be blank") @NotBlank
@Pattern(regexp = "otpauth://totp/(\\S+?):(\\S+?)\\?issuer=(\\S+?)&secret=(\\w+?)", message = "OTP auth url is invalid") @Pattern(regexp = "otpauth://totp/(\\S+?):(\\S+?)\\?issuer=(\\S+?)&secret=(\\w+?)", message = "is invalid")
private String authUrl; private String authUrl;
@Override @Override

2
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/BackupCodeTwoFaProviderConfig.java

@ -22,7 +22,7 @@ import javax.validation.constraints.Min;
@Data @Data
public class BackupCodeTwoFaProviderConfig implements TwoFaProviderConfig { public class BackupCodeTwoFaProviderConfig implements TwoFaProviderConfig {
@Min(value = 1, message = "backup codes quantity must be greater than 0") @Min(value = 1, message = "must be greater than 0")
private int codesQuantity; private int codesQuantity;
@Override @Override

2
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/OtpBasedTwoFaProviderConfig.java

@ -22,7 +22,7 @@ import javax.validation.constraints.Min;
@Data @Data
public abstract class OtpBasedTwoFaProviderConfig implements TwoFaProviderConfig { public abstract class OtpBasedTwoFaProviderConfig implements TwoFaProviderConfig {
@Min(value = 1, message = "verification code lifetime is required") @Min(value = 1, message = "is required")
private int verificationCodeLifetime; private int verificationCodeLifetime;
} }

4
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/SmsTwoFaProviderConfig.java

@ -25,8 +25,8 @@ import javax.validation.constraints.Pattern;
@Data @Data
public class SmsTwoFaProviderConfig extends OtpBasedTwoFaProviderConfig { public class SmsTwoFaProviderConfig extends OtpBasedTwoFaProviderConfig {
@NotBlank(message = "verification message template is required") @NotBlank(message = "is required")
@Pattern(regexp = ".*\\$\\{code}.*", message = "template must contain verification code") @Pattern(regexp = ".*\\$\\{code}.*", message = "must contain verification code")
private String smsVerificationMessageTemplate; private String smsVerificationMessageTemplate;
@Override @Override

2
common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/TotpTwoFaProviderConfig.java

@ -22,7 +22,7 @@ import javax.validation.constraints.NotBlank;
@Data @Data
public class TotpTwoFaProviderConfig implements TwoFaProviderConfig { public class TotpTwoFaProviderConfig implements TwoFaProviderConfig {
@NotBlank(message = "issuer name must not be blank") @NotBlank
private String issuerName; private String issuerName;
@Override @Override

18
dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java

@ -18,6 +18,7 @@ package org.thingsboard.server.dao;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -94,11 +95,18 @@ public abstract class DaoUtil {
} }
public static UUID getId(UUIDBased idBased) { public static UUID getId(UUIDBased idBased) {
UUID id = null; return getId(idBased, false);
if (idBased != null) { }
id = idBased.getId();
public static UUID getId(UUIDBased uuidBased, boolean nullUuidToNull) {
UUID uuid = null;
if (uuidBased != null) {
uuid = uuidBased.getId();
if (nullUuidToNull && uuid.equals(EntityId.NULL_UUID)) {
uuid = null;
}
} }
return id; return uuid;
} }
public static List<UUID> toUUIDs(List<? extends UUIDBased> idBasedIds) { public static List<UUID> toUUIDs(List<? extends UUIDBased> idBasedIds) {
@ -110,7 +118,7 @@ public abstract class DaoUtil {
} }
public static <T> void processInBatches(Function<PageLink, PageData<T>> finder, int batchSize, Consumer<T> processor) { public static <T> void processInBatches(Function<PageLink, PageData<T>> finder, int batchSize, Consumer<T> processor) {
processBatches(finder, batchSize, batch -> batch.getData().forEach(processor)); processBatches(finder, batchSize, batch -> batch.getData().forEach(processor));
} }
public static <T> void processBatches(Function<PageLink, PageData<T>> finder, int batchSize, Consumer<PageData<T>> processor) { public static <T> void processBatches(Function<PageLink, PageData<T>> finder, int batchSize, Consumer<PageData<T>> processor) {

7
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationRuleService.java

@ -22,7 +22,6 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.rule.NotificationRule; import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.service.DataValidator;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@ -30,11 +29,8 @@ public class DefaultNotificationRuleService implements NotificationRuleService {
private final NotificationRuleDao notificationRuleDao; private final NotificationRuleDao notificationRuleDao;
private final NotificationRuleValidator validator = new NotificationRuleValidator();
@Override @Override
public NotificationRule saveNotificationRule(TenantId tenantId, NotificationRule notificationRule) { public NotificationRule saveNotificationRule(TenantId tenantId, NotificationRule notificationRule) {
validator.validate(notificationRule, NotificationRule::getTenantId);
return notificationRuleDao.save(tenantId, notificationRule); return notificationRuleDao.save(tenantId, notificationRule);
} }
@ -53,7 +49,4 @@ public class DefaultNotificationRuleService implements NotificationRuleService {
notificationRuleDao.removeById(tenantId, id.getId()); notificationRuleDao.removeById(tenantId, id.getId());
} }
private static class NotificationRuleValidator extends DataValidator<NotificationRule> {
}
} }

7
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTemplateService.java

@ -21,6 +21,8 @@ import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus; import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; 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 org.thingsboard.server.dao.entity.AbstractEntityService;
import java.util.Map; import java.util.Map;
@ -42,6 +44,11 @@ public class DefaultNotificationTemplateService extends AbstractEntityService im
return notificationTemplateDao.save(tenantId, notificationTemplate); return notificationTemplateDao.save(tenantId, notificationTemplate);
} }
@Override
public PageData<NotificationTemplate> findNotificationTemplatesByTenantId(TenantId tenantId, PageLink pageLink) {
return notificationTemplateDao.findByTenantIdAndPageLink(tenantId, pageLink);
}
@Override @Override
public void deleteNotificationTemplateById(TenantId tenantId, NotificationTemplateId id) { public void deleteNotificationTemplateById(TenantId tenantId, NotificationTemplateId id) {
if (notificationRequestDao.existsByStatusAndTemplateId(tenantId, NotificationRequestStatus.SCHEDULED, id)) { if (notificationRequestDao.existsByStatusAndTemplateId(tenantId, NotificationRequestStatus.SCHEDULED, id)) {

6
dao/src/main/java/org/thingsboard/server/dao/notification/NotificationTemplateDao.java

@ -15,8 +15,14 @@
*/ */
package org.thingsboard.server.dao.notification; package org.thingsboard.server.dao.notification;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; 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 org.thingsboard.server.dao.Dao;
public interface NotificationTemplateDao extends Dao<NotificationTemplate> { public interface NotificationTemplateDao extends Dao<NotificationTemplate> {
PageData<NotificationTemplate> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink);
} }

6
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationDao.java

@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationId;
import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -97,4 +98,9 @@ public class JpaNotificationDao extends JpaAbstractDao<NotificationEntity, Notif
return notificationRepository; return notificationRepository;
} }
@Override
public EntityType getEntityType() {
return EntityType.NOTIFICATION;
}
} }

4
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRequestDao.java

@ -41,6 +41,8 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.dao.DaoUtil.getId;
@Component @Component
@SqlDao @SqlDao
@RequiredArgsConstructor @RequiredArgsConstructor
@ -50,7 +52,7 @@ public class JpaNotificationRequestDao extends JpaAbstractDao<NotificationReques
@Override @Override
public PageData<NotificationRequest> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) { public PageData<NotificationRequest> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationRequestRepository.findByTenantId(tenantId.getId(), DaoUtil.toPageable(pageLink))); return DaoUtil.toPageData(notificationRequestRepository.findByTenantId(getId(tenantId, true), DaoUtil.toPageable(pageLink)));
} }
@Override @Override

4
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationRuleDao.java

@ -33,6 +33,8 @@ import org.thingsboard.server.dao.util.SqlDao;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.getId;
@Component @Component
@SqlDao @SqlDao
@RequiredArgsConstructor @RequiredArgsConstructor
@ -42,7 +44,7 @@ public class JpaNotificationRuleDao extends JpaAbstractDao<NotificationRuleEntit
@Override @Override
public PageData<NotificationRule> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) { public PageData<NotificationRule> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationRuleRepository.findByTenantIdAndNameContainingIgnoreCase(tenantId.getId(), return DaoUtil.toPageData(notificationRuleRepository.findByTenantIdAndNameContainingIgnoreCase(getId(tenantId, true),
Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink))); Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink)));
} }

4
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTargetDao.java

@ -32,6 +32,8 @@ import org.thingsboard.server.dao.util.SqlDao;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.getId;
@Component @Component
@SqlDao @SqlDao
@RequiredArgsConstructor @RequiredArgsConstructor
@ -41,7 +43,7 @@ public class JpaNotificationTargetDao extends JpaAbstractDao<NotificationTargetE
@Override @Override
public PageData<NotificationTarget> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) { public PageData<NotificationTarget> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationTargetRepository.findByTenantIdAndNameContainingIgnoreCase(tenantId.getId(), return DaoUtil.toPageData(notificationTargetRepository.findByTenantIdAndNameContainingIgnoreCase(getId(tenantId, true),
Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink))); Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink)));
} }

13
dao/src/main/java/org/thingsboard/server/dao/sql/notification/JpaNotificationTemplateDao.java

@ -15,11 +15,16 @@
*/ */
package org.thingsboard.server.dao.sql.notification; package org.thingsboard.server.dao.sql.notification;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; 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.DaoUtil;
import org.thingsboard.server.dao.model.sql.NotificationTemplateEntity; import org.thingsboard.server.dao.model.sql.NotificationTemplateEntity;
import org.thingsboard.server.dao.notification.NotificationTemplateDao; import org.thingsboard.server.dao.notification.NotificationTemplateDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.sql.JpaAbstractDao;
@ -27,6 +32,8 @@ import org.thingsboard.server.dao.util.SqlDao;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.dao.DaoUtil.getId;
@Component @Component
@SqlDao @SqlDao
@RequiredArgsConstructor @RequiredArgsConstructor
@ -39,6 +46,12 @@ public class JpaNotificationTemplateDao extends JpaAbstractDao<NotificationTempl
return NotificationTemplateEntity.class; return NotificationTemplateEntity.class;
} }
@Override
public PageData<NotificationTemplate> findByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(notificationTemplateRepository.findByTenantIdAndSearchText(getId(tenantId, true),
Strings.nullToEmpty(pageLink.getTextSearch()), DaoUtil.toPageable(pageLink)));
}
@Override @Override
protected JpaRepository<NotificationTemplateEntity, UUID> getRepository() { protected JpaRepository<NotificationTemplateEntity, UUID> getRepository() {
return notificationTemplateRepository; return notificationTemplateRepository;

12
dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationTemplateRepository.java

@ -15,7 +15,11 @@
*/ */
package org.thingsboard.server.dao.sql.notification; package org.thingsboard.server.dao.sql.notification;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; 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.springframework.stereotype.Repository;
import org.thingsboard.server.dao.model.sql.NotificationTemplateEntity; import org.thingsboard.server.dao.model.sql.NotificationTemplateEntity;
@ -23,4 +27,12 @@ import java.util.UUID;
@Repository @Repository
public interface NotificationTemplateRepository extends JpaRepository<NotificationTemplateEntity, UUID> { public interface NotificationTemplateRepository extends JpaRepository<NotificationTemplateEntity, UUID> {
@Query("SELECT t FROM NotificationTemplateEntity t WHERE t.tenantId = :tenantId AND " +
"(lower(t.name) LIKE lower(concat('%', :searchText, '%')) OR " +
"lower(t.notificationType) LIKE lower(concat('%', :searchText, '%')))")
Page<NotificationTemplateEntity> findByTenantIdAndSearchText(@Param("tenantId") UUID tenantId,
@Param("searchText") String searchText,
Pageable pageable);
} }

Loading…
Cancel
Save