From 3b8ed5fae639778c2d151f1946797369bbade2c6 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 17 Mar 2023 14:03:03 +0200 Subject: [PATCH] Notification rules improvements; new platform users filters --- .../server/actors/ActorSystemContext.java | 2 +- .../NotificationTargetController.java | 26 ++++++++++---- .../server/controller/UserController.java | 5 +-- .../NotificationExecutorService.java | 2 +- .../DefaultNotificationCenter.java | 23 +++++++++++-- ...aultNotificationRuleProcessingService.java | 3 +- .../AlarmAssignmentTriggerProcessor.java | 6 ++-- .../trigger/AlarmCommentTriggerProcessor.java | 5 ++- .../rule/trigger/AlarmTriggerProcessor.java | 6 +++- .../queue/DefaultTbCoreConsumerService.java | 3 +- .../DefaultTbRuleEngineConsumerService.java | 1 - .../service/slack/DefaultSlackService.java | 7 ++-- .../DefaultAlarmSubscriptionService.java | 2 +- .../service/update/DefaultUpdateService.java | 2 +- .../src/main/resources/thingsboard.yml | 2 +- .../notification/NotificationRuleApiTest.java | 6 ++-- .../NotificationRuleProcessingService.java | 2 +- .../server/dao/user/UserService.java | 11 +++++- .../server/common/data/EntityType.java | 9 ++++- .../info/AlarmAssignmentNotificationInfo.java | 11 +++++- .../info/AlarmCommentNotificationInfo.java | 4 ++- .../info/AlarmNotificationInfo.java | 5 +-- .../info/EntitiesLimitNotificationInfo.java | 3 +- .../info/EntityActionNotificationInfo.java | 2 +- ...mponentLifecycleEventNotificationInfo.java | 4 +-- .../info/RuleOriginatedNotificationInfo.java | 5 +++ ...signmentNotificationRuleTriggerConfig.java | 1 + ...mCommentNotificationRuleTriggerConfig.java | 1 + .../platform/ActionTargetUserFilter.java | 28 +++++++++++++++ .../platform/TenantAdministratorsFilter.java | 34 +++++++++++++++++++ .../targets/platform/UsersFilter.java | 4 ++- .../targets/platform/UsersFilterType.java | 6 +++- .../DefaultNotificationTargetService.java | 24 +++++++++++-- .../server/dao/service/DataValidator.java | 2 +- .../server/dao/sql/user/JpaUserDao.java | 20 ++++++++++- .../server/dao/sql/user/UserRepository.java | 13 ++++++- .../usagerecord}/DefaultApiLimitService.java | 12 ++++--- .../thingsboard/server/dao/user/UserDao.java | 11 +++++- .../server/dao/user/UserServiceImpl.java | 22 ++++++++++-- 39 files changed, 273 insertions(+), 62 deletions(-) rename {application/src/main/java/org/thingsboard/server/service/notification/rule => common/dao-api/src/main/java/org/thingsboard/server/dao/notification}/NotificationRuleProcessingService.java (96%) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/ActionTargetUserFilter.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/TenantAdministratorsFilter.java rename {application/src/main/java/org/thingsboard/server/service/apiusage => dao/src/main/java/org/thingsboard/server/dao/usagerecord}/DefaultApiLimitService.java (81%) diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 532fc5090c..9ec8020544 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -95,7 +95,7 @@ import org.thingsboard.server.service.executors.ExternalCallExecutorService; import org.thingsboard.server.service.executors.NotificationExecutorService; import org.thingsboard.server.service.executors.SharedEventLoopGroupService; import org.thingsboard.server.service.mail.MailExecutorService; -import org.thingsboard.server.service.notification.rule.NotificationRuleProcessingService; +import org.thingsboard.server.dao.notification.NotificationRuleProcessingService; import org.thingsboard.server.service.profile.TbAssetProfileCache; import org.thingsboard.server.service.profile.TbDeviceProfileCache; import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java index 4f4380c2df..815bcf0af5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java @@ -18,6 +18,8 @@ package org.thingsboard.server.controller; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; @@ -39,6 +41,7 @@ import org.thingsboard.server.common.data.notification.targets.NotificationTarge import org.thingsboard.server.common.data.notification.targets.NotificationTargetType; import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter; import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig; +import org.thingsboard.server.common.data.notification.targets.platform.TenantAdministratorsFilter; import org.thingsboard.server.common.data.notification.targets.platform.UserListFilter; import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter; import org.thingsboard.server.common.data.notification.targets.platform.UsersFilterType; @@ -159,13 +162,22 @@ public class NotificationTargetController extends BaseController { } // generic permission for users UsersFilter usersFilter = ((PlatformUsersNotificationTargetConfig) targetConfig).getUsersFilter(); - if (usersFilter.getType() == UsersFilterType.USER_LIST) { - for (UUID recipientId : ((UserListFilter) usersFilter).getUsersIds()) { - checkUserId(new UserId(recipientId), Operation.READ); - } - } else if (usersFilter.getType() == UsersFilterType.CUSTOMER_USERS) { - CustomerId customerId = new CustomerId(((CustomerUsersFilter) usersFilter).getCustomerId()); - checkEntityId(customerId, Operation.READ); + switch (usersFilter.getType()) { + case USER_LIST: + for (UUID recipientId : ((UserListFilter) usersFilter).getUsersIds()) { + checkUserId(new UserId(recipientId), Operation.READ); + } + break; + case CUSTOMER_USERS: + CustomerId customerId = new CustomerId(((CustomerUsersFilter) usersFilter).getCustomerId()); + checkEntityId(customerId, Operation.READ); + break; + case TENANT_ADMINISTRATORS: + if (CollectionUtils.isNotEmpty(((TenantAdministratorsFilter) usersFilter).getTenantsIds()) || + CollectionUtils.isNotEmpty(((TenantAdministratorsFilter) usersFilter).getTenantProfilesIds())) { + throw new AccessDeniedException(""); + } + break; } } diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index e57bb73262..06963e466f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -58,9 +57,9 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.UserSettings; import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent; +import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.user.TbUserService; -import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.service.query.EntityQueryService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.UserPrincipal; @@ -70,7 +69,6 @@ import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.system.SystemSecurityService; import javax.servlet.http.HttpServletRequest; - import java.util.Arrays; import java.util.List; import java.util.Map; @@ -109,7 +107,6 @@ public class UserController extends BaseController { public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; @Value("${security.user_token_access_enabled}") - @Getter private boolean userTokenAccessEnabled; private final MailService mailService; diff --git a/application/src/main/java/org/thingsboard/server/service/executors/NotificationExecutorService.java b/application/src/main/java/org/thingsboard/server/service/executors/NotificationExecutorService.java index 53d55fdad6..81ad36a4a1 100644 --- a/application/src/main/java/org/thingsboard/server/service/executors/NotificationExecutorService.java +++ b/application/src/main/java/org/thingsboard/server/service/executors/NotificationExecutorService.java @@ -22,7 +22,7 @@ import org.thingsboard.common.util.AbstractListeningExecutor; @Component public class NotificationExecutorService extends AbstractListeningExecutor { - @Value("${notification_system.thread_pool_size:30}") + @Value("${notification_system.thread_pool_size:10}") private int threadPoolSize; @Override diff --git a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java index 81c0fbf6a5..5d8f22ecde 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java @@ -39,9 +39,12 @@ 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; import org.thingsboard.server.common.data.notification.targets.NotificationTarget; +import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig; +import org.thingsboard.server.common.data.notification.targets.platform.UsersFilterType; import org.thingsboard.server.common.data.notification.targets.slack.SlackNotificationTargetConfig; import org.thingsboard.server.common.data.notification.template.DeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; @@ -56,6 +59,7 @@ import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.notification.NotificationTargetService; import org.thingsboard.server.dao.notification.NotificationTemplateService; +import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.NotificationsTopicService; @@ -89,6 +93,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple private final NotificationService notificationService; private final NotificationTemplateService notificationTemplateService; private final NotificationSettingsService notificationSettingsService; + private final UserService userService; private final NotificationExecutorService notificationExecutor; private final DbCallbackExecutorService dbCallbackExecutorService; private final NotificationsTopicService notificationsTopicService; @@ -186,9 +191,21 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple Iterable recipients; switch (target.getConfiguration().getType()) { case PLATFORM_USERS: { - recipients = new PageDataIterable<>(pageLink -> { - return notificationTargetService.findRecipientsForNotificationTargetConfig(ctx.getTenantId(), ctx.getCustomerId(), target.getConfiguration(), pageLink); - }, 200); + PlatformUsersNotificationTargetConfig platformUsersTargetConfig = (PlatformUsersNotificationTargetConfig) target.getConfiguration(); + if (platformUsersTargetConfig.getUsersFilter().getType() == UsersFilterType.ACTION_TARGET_USER) { + if (ctx.getRequest().getInfo() instanceof RuleOriginatedNotificationInfo) { + UserId targetUserId = ((RuleOriginatedNotificationInfo) ctx.getRequest().getInfo()).getTargetUserId(); + if (targetUserId != null) { + recipients = List.of(userService.findUserById(ctx.getTenantId(), targetUserId)); + break; + } + } + recipients = Collections.emptyList(); + } else { + recipients = new PageDataIterable<>(pageLink -> { + return notificationTargetService.findRecipientsForNotificationTargetConfig(ctx.getTenantId(), ctx.getCustomerId(), platformUsersTargetConfig, pageLink); + }, 500); + } break; } case SLACK: { diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java index 5d89983b04..b197816a8f 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessingService.java @@ -39,12 +39,11 @@ import org.thingsboard.server.common.data.notification.rule.trigger.Notification import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; -import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.dao.alarm.AlarmApiCallResult; import org.thingsboard.server.dao.notification.NotificationRequestService; +import org.thingsboard.server.dao.notification.NotificationRuleProcessingService; import org.thingsboard.server.dao.notification.NotificationRuleService; import org.thingsboard.server.service.executors.NotificationExecutorService; -import org.thingsboard.server.service.notification.rule.trigger.EntitiesLimitTriggerProcessor.EntitiesLimitTriggerObject; import org.thingsboard.server.service.notification.rule.trigger.NotificationRuleTriggerProcessor; import org.thingsboard.server.service.notification.rule.trigger.RuleEngineComponentLifecycleEventTriggerProcessor.RuleEngineComponentLifecycleEventTriggerObject; import org.thingsboard.server.service.notification.rule.trigger.RuleEngineMsgNotificationRuleTriggerProcessor; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java index 6ccff5686f..e3ecef5ef1 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java @@ -37,7 +37,8 @@ public class AlarmAssignmentTriggerProcessor implements RuleEngineMsgNotificatio @Override public boolean matchesFilter(TbMsg ruleEngineMsg, AlarmAssignmentNotificationRuleTriggerConfig triggerConfig) { - if (ruleEngineMsg.getType().equals(DataConstants.ALARM_UNASSIGN) && !triggerConfig.isNotifyOnUnassign()) { + if ((ruleEngineMsg.getType().equals(DataConstants.ALARM_ASSIGN) && !triggerConfig.isNotifyOnAssign()) + || (ruleEngineMsg.getType().equals(DataConstants.ALARM_UNASSIGN) && !triggerConfig.isNotifyOnUnassign())) { return false; } Alarm alarm = JacksonUtil.fromString(ruleEngineMsg.getData(), Alarm.class); @@ -48,13 +49,14 @@ public class AlarmAssignmentTriggerProcessor implements RuleEngineMsgNotificatio @Override public NotificationInfo constructNotificationInfo(TbMsg ruleEngineMsg, AlarmAssignmentNotificationRuleTriggerConfig triggerConfig) { - // TODO: readable action AlarmInfo alarmInfo = JacksonUtil.fromString(ruleEngineMsg.getData(), AlarmInfo.class); AlarmAssignee assignee = alarmInfo.getAssignee(); return AlarmAssignmentNotificationInfo.builder() + .action(ruleEngineMsg.getType().equals(DataConstants.ALARM_ASSIGN) ? "assigned" : "unassigned") .assigneeFirstName(assignee != null ? assignee.getFirstName() : null) .assigneeLastName(assignee != null ? assignee.getLastName() : null) .assigneeEmail(assignee != null ? assignee.getEmail() : null) + .assigneeId(assignee != null ? assignee.getId() : null) .userName(ruleEngineMsg.getMetaData().getValue("userName")) .alarmId(alarmInfo.getUuidId()) .alarmType(alarmInfo.getType()) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java index 8be6e1622b..df9ff12c17 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java @@ -41,6 +41,9 @@ public class AlarmCommentTriggerProcessor implements RuleEngineMsgNotificationRu if (ruleEngineMsg.getMetaData().getValue("comment") == null) { return false; } + if (ruleEngineMsg.getType().equals(DataConstants.COMMENT_UPDATED) && !triggerConfig.isNotifyOnCommentUpdate()) { + return false; + } if (triggerConfig.isOnlyUserComments()) { AlarmComment comment = JacksonUtil.fromString(ruleEngineMsg.getMetaData().getValue("comment"), AlarmComment.class); if (comment.getType() == AlarmCommentType.SYSTEM) { @@ -55,11 +58,11 @@ public class AlarmCommentTriggerProcessor implements RuleEngineMsgNotificationRu @Override public NotificationInfo constructNotificationInfo(TbMsg ruleEngineMsg, AlarmCommentNotificationRuleTriggerConfig triggerConfig) { - // TODO: readable action AlarmComment comment = JacksonUtil.fromString(ruleEngineMsg.getMetaData().getValue("comment"), AlarmComment.class); AlarmInfo alarmInfo = JacksonUtil.fromString(ruleEngineMsg.getData(), AlarmInfo.class); return AlarmCommentNotificationInfo.builder() .comment(comment.getComment().get("text").asText()) + .action(ruleEngineMsg.getType().equals(DataConstants.COMMENT_CREATED) ? "created" : "updated") .userName(ruleEngineMsg.getMetaData().getValue("userName")) .alarmId(alarmInfo.getUuidId()) .alarmType(alarmInfo.getType()) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java index babe177eea..31af9e2333 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java @@ -91,11 +91,15 @@ public class AlarmTriggerProcessor implements NotificationRuleTriggerProcessor findTenantAdmins(TenantId tenantId, PageLink pageLink); - PageData findAllUsers(TenantId tenantId, PageLink pageLink); + PageData findAllTenantAdmins(PageLink pageLink); + + PageData findTenantAdminsByTenantsIds(List tenantsIds, PageLink pageLink); + + PageData findTenantAdminsByTenantProfilesIds(List tenantProfilesIds, PageLink pageLink); + + PageData findAllUsers(PageLink pageLink); void deleteTenantAdmins(TenantId tenantId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index 472d73adb6..2763479cfe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.common.data; +import org.apache.commons.lang3.StringUtils; + /** * @author Andrew Shvayka */ @@ -44,5 +46,10 @@ public enum EntityType { NOTIFICATION_TEMPLATE, NOTIFICATION_REQUEST, NOTIFICATION, - NOTIFICATION_RULE + NOTIFICATION_RULE; + + public String normalName() { + return StringUtils.capitalize(name().toLowerCase().replaceAll("_", " ")); + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmAssignmentNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmAssignmentNotificationInfo.java index 815bf4e3db..1edd9621ce 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmAssignmentNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmAssignmentNotificationInfo.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.UserId; import java.util.Map; import java.util.UUID; @@ -35,9 +36,11 @@ import static org.thingsboard.server.common.data.util.CollectionsUtil.mapOf; @Builder public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificationInfo { + private String action; private String assigneeFirstName; private String assigneeLastName; private String assigneeEmail; + private UserId assigneeId; private String userName; private String alarmType; @@ -51,6 +54,7 @@ public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificati @Override public Map getTemplateData() { return mapOf( + "action", action, "assigneeFirstName", assigneeFirstName, "assigneeLastName", assigneeLastName, "assigneeEmail", assigneeEmail, @@ -59,7 +63,7 @@ public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificati "alarmId", alarmId.toString(), "alarmSeverity", alarmSeverity.toString(), "alarmStatus", alarmStatus.toString(), - "alarmOriginatorEntityType", alarmOriginator.getEntityType().toString(), + "alarmOriginatorEntityType", alarmOriginator.getEntityType().normalName(), "alarmOriginatorId", alarmOriginator.getId().toString(), "alarmOriginatorName", alarmOriginatorName ); @@ -70,6 +74,11 @@ public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificati return alarmCustomerId; } + @Override + public UserId getTargetUserId() { + return assigneeId; + } + @Override public EntityId getStateEntityId() { return alarmOriginator; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmCommentNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmCommentNotificationInfo.java index 3fce737194..3afb5ff31f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmCommentNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmCommentNotificationInfo.java @@ -36,6 +36,7 @@ import static org.thingsboard.server.common.data.util.CollectionsUtil.mapOf; public class AlarmCommentNotificationInfo implements RuleOriginatedNotificationInfo { private String comment; + private String action; private String userName; private String alarmType; private UUID alarmId; @@ -49,12 +50,13 @@ public class AlarmCommentNotificationInfo implements RuleOriginatedNotificationI public Map getTemplateData() { return mapOf( "comment", comment, + "action", action, "userName", userName, "alarmType", alarmType, "alarmId", alarmId.toString(), "alarmSeverity", alarmSeverity.toString(), "alarmStatus", alarmStatus.toString(), - "alarmOriginatorEntityType", alarmOriginator.getEntityType().toString(), + "alarmOriginatorEntityType", alarmOriginator.getEntityType().normalName(), "alarmOriginatorId", alarmOriginator.getId().toString(), "alarmOriginatorName", alarmOriginatorName ); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java index 502d6069dd..449ea776af 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java @@ -36,6 +36,7 @@ import static org.thingsboard.server.common.data.util.CollectionsUtil.mapOf; public class AlarmNotificationInfo implements RuleOriginatedNotificationInfo { private String alarmType; + private String action; private UUID alarmId; private EntityId alarmOriginator; private String alarmOriginatorName; @@ -45,13 +46,13 @@ public class AlarmNotificationInfo implements RuleOriginatedNotificationInfo { @Override public Map getTemplateData() { - // TODO: readable status change return mapOf( "alarmType", alarmType, + "action", action, "alarmId", alarmId.toString(), "alarmSeverity", alarmSeverity.toString(), "alarmStatus", alarmStatus.toString(), - "alarmOriginatorEntityType", alarmOriginator.getEntityType().toString(), + "alarmOriginatorEntityType", alarmOriginator.getEntityType().normalName(), "alarmOriginatorName", alarmOriginatorName, "alarmOriginatorId", alarmOriginator.getId().toString() ); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntitiesLimitNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntitiesLimitNotificationInfo.java index add9f9d5d7..0cd5e78cf6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntitiesLimitNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntitiesLimitNotificationInfo.java @@ -36,9 +36,8 @@ public class EntitiesLimitNotificationInfo implements NotificationInfo { @Override public Map getTemplateData() { - // FIXME: readable entity type name, e.g. 'Devices' return mapOf( - "entityType", entityType.name(), + "entityType", entityType.normalName(), "threshold", String.valueOf(threshold) ); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java index b7e49183ea..4ad2172ac6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/EntityActionNotificationInfo.java @@ -49,7 +49,7 @@ public class EntityActionNotificationInfo implements RuleOriginatedNotificationI @Override public Map getTemplateData() { return mapOf( - "entityType", entityId.getEntityType().name(), + "entityType", entityId.getEntityType().normalName(), "entityId", entityId.toString(), "entityName", entityName, "actionType", actionType.name().toLowerCase(), diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleEngineComponentLifecycleEventNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleEngineComponentLifecycleEventNotificationInfo.java index 45c1c689ac..80ceb8a332 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleEngineComponentLifecycleEventNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleEngineComponentLifecycleEventNotificationInfo.java @@ -46,9 +46,9 @@ public class RuleEngineComponentLifecycleEventNotificationInfo implements Notifi "ruleChainId", ruleChainId.toString(), "ruleChainName", ruleChainName, "componentId", componentId.toString(), - "componentType", componentId.getEntityType().name(), + "componentType", componentId.getEntityType().normalName(), "componentName", componentName, - "eventType", eventType.name(), + "eventType", eventType.name().toLowerCase(), "error", error ); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleOriginatedNotificationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleOriginatedNotificationInfo.java index 6ab22dcf05..91320d7571 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleOriginatedNotificationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleOriginatedNotificationInfo.java @@ -16,9 +16,14 @@ package org.thingsboard.server.common.data.notification.info; import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.UserId; public interface RuleOriginatedNotificationInfo extends NotificationInfo { CustomerId getOriginatorEntityCustomerId(); + default UserId getTargetUserId() { + return null; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java index 88e2c5fd76..2434e2ea0f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java @@ -27,6 +27,7 @@ public class AlarmAssignmentNotificationRuleTriggerConfig implements Notificatio private Set alarmTypes; private Set alarmSeverities; private Set alarmStatuses; + private boolean notifyOnAssign; private boolean notifyOnUnassign; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmCommentNotificationRuleTriggerConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmCommentNotificationRuleTriggerConfig.java index 3cfdd7ae3c..237dce5282 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmCommentNotificationRuleTriggerConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmCommentNotificationRuleTriggerConfig.java @@ -28,6 +28,7 @@ public class AlarmCommentNotificationRuleTriggerConfig implements NotificationRu private Set alarmSeverities; private Set alarmStatuses; private boolean onlyUserComments; + private boolean notifyOnCommentUpdate; @Override public NotificationRuleTriggerType getTriggerType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/ActionTargetUserFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/ActionTargetUserFilter.java new file mode 100644 index 0000000000..54d88ddccf --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/ActionTargetUserFilter.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.notification.targets.platform; + +import lombok.Data; + +@Data +public class ActionTargetUserFilter implements UsersFilter { + + @Override + public UsersFilterType getType() { + return UsersFilterType.ACTION_TARGET_USER; + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/TenantAdministratorsFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/TenantAdministratorsFilter.java new file mode 100644 index 0000000000..1176a59fa8 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/TenantAdministratorsFilter.java @@ -0,0 +1,34 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.notification.targets.platform; + +import lombok.Data; + +import java.util.Set; +import java.util.UUID; + +@Data +public class TenantAdministratorsFilter implements UsersFilter { + + private Set tenantsIds; + private Set tenantProfilesIds; + + @Override + public UsersFilterType getType() { + return UsersFilterType.TENANT_ADMINISTRATORS; + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilter.java index 0a49d93d40..7131a060cb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilter.java @@ -26,8 +26,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; @JsonSubTypes({ @Type(value = UserListFilter.class, name = "USER_LIST"), @Type(value = CustomerUsersFilter.class, name = "CUSTOMER_USERS"), + @Type(value = TenantAdministratorsFilter.class, name = "TENANT_ADMINISTRATORS"), @Type(value = AllUsersFilter.class, name = "ALL_USERS"), - @Type(value = OriginatorEntityOwnerUsersFilter.class, name = "ORIGINATOR_ENTITY_OWNER_USERS") // for usage in notification rules + @Type(value = OriginatorEntityOwnerUsersFilter.class, name = "ORIGINATOR_ENTITY_OWNER_USERS"), + @Type(value = ActionTargetUserFilter.class, name = "ACTION_TARGET_USER") }) public interface UsersFilter { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilterType.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilterType.java index 86e1ec7f87..e205c4c3dc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilterType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UsersFilterType.java @@ -16,8 +16,12 @@ package org.thingsboard.server.common.data.notification.targets.platform; public enum UsersFilterType { + USER_LIST, CUSTOMER_USERS, + TENANT_ADMINISTRATORS, ALL_USERS, - ORIGINATOR_ENTITY_OWNER_USERS + ORIGINATOR_ENTITY_OWNER_USERS, + ACTION_TARGET_USER + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java index e1089b703a..01180c6ee4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java @@ -25,13 +25,14 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.NotificationRequestStatus; import org.thingsboard.server.common.data.notification.targets.NotificationTarget; import org.thingsboard.server.common.data.notification.targets.NotificationTargetConfig; import org.thingsboard.server.common.data.notification.targets.platform.CustomerUsersFilter; -import org.thingsboard.server.common.data.notification.targets.platform.OriginatorEntityOwnerUsersFilter; import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig; +import org.thingsboard.server.common.data.notification.targets.platform.TenantAdministratorsFilter; import org.thingsboard.server.common.data.notification.targets.platform.UserListFilter; import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter; import org.thingsboard.server.common.data.page.PageData; @@ -46,6 +47,8 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; + @Service @Slf4j @RequiredArgsConstructor @@ -117,15 +120,30 @@ public class DefaultNotificationTargetService extends AbstractEntityService impl CustomerUsersFilter filter = (CustomerUsersFilter) usersFilter; return userService.findCustomerUsers(tenantId, new CustomerId(filter.getCustomerId()), pageLink); } + case TENANT_ADMINISTRATORS: { + TenantAdministratorsFilter filter = (TenantAdministratorsFilter) usersFilter; + if (!tenantId.equals(TenantId.SYS_TENANT_ID)) { + return userService.findTenantAdmins(tenantId, pageLink); + } else { + if (isNotEmpty(filter.getTenantsIds())) { + return userService.findTenantAdminsByTenantsIds(filter.getTenantsIds().stream() + .map(TenantId::fromUUID).collect(Collectors.toList()), pageLink); + } else if (isNotEmpty(filter.getTenantProfilesIds())) { + return userService.findTenantAdminsByTenantProfilesIds(filter.getTenantProfilesIds().stream() + .map(TenantProfileId::new).collect(Collectors.toList()), pageLink); + } else { + return userService.findAllTenantAdmins(pageLink); + } + } + } case ALL_USERS: { if (!tenantId.equals(TenantId.SYS_TENANT_ID)) { return userService.findUsersByTenantId(tenantId, pageLink); } else { - return userService.findAllUsers(TenantId.SYS_TENANT_ID, pageLink); + return userService.findAllUsers(pageLink); } } case ORIGINATOR_ENTITY_OWNER_USERS: { - OriginatorEntityOwnerUsersFilter filter = (OriginatorEntityOwnerUsersFilter) usersFilter; if (customerId != null && !customerId.isNullUid()) { return userService.findCustomerUsers(tenantId, customerId, pageLink); } else { diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java index e95fee79ae..131a6a619e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java @@ -106,7 +106,7 @@ public abstract class DataValidator> { protected void validateNumberOfEntitiesPerTenant(TenantId tenantId, EntityType entityType) { if (!apiLimitService.checkEntitiesLimit(tenantId, entityType)) { - throw new DataValidationException(String.format("%ss limit reached", capitalize(entityType.name().toLowerCase().replaceAll("_", " ")))); + throw new DataValidationException(entityType.normalName() + "s limit reached"); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java index c745648b4b..4a41fc17a4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; @@ -30,6 +31,7 @@ import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.user.UserDao; import org.thingsboard.server.dao.util.SqlDao; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -101,10 +103,26 @@ public class JpaUserDao extends JpaAbstractSearchTextDao imple } @Override - public PageData findAll(TenantId tenantId, PageLink pageLink) { + public PageData findAll(PageLink pageLink) { return DaoUtil.toPageData(userRepository.findAll(DaoUtil.toPageable(pageLink))); } + @Override + public PageData findAllByAuthority(Authority authority, PageLink pageLink) { + return DaoUtil.toPageData(userRepository.findAllByAuthority(authority, DaoUtil.toPageable(pageLink))); + } + + @Override + public PageData findByAuthorityAndTenantsIds(Authority authority, List tenantsIds, PageLink pageLink) { + return DaoUtil.toPageData(userRepository.findByAuthorityAndTenantIdIn(authority, DaoUtil.toUUIDs(tenantsIds), DaoUtil.toPageable(pageLink))); + } + + @Override + public PageData findByAuthorityAndTenantProfilesIds(Authority authority, List tenantProfilesIds, PageLink pageLink) { + return DaoUtil.toPageData(userRepository.findByAuthorityAndTenantProfilesIds(authority, DaoUtil.toUUIDs(tenantProfilesIds), + DaoUtil.toPageable(pageLink))); + } + @Override public Long countByTenantId(TenantId tenantId) { return userRepository.countByTenantId(tenantId.getId()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java index 8a7ee7d581..e00c73763b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java @@ -20,10 +20,10 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.sql.UserEntity; +import java.util.Collection; import java.util.UUID; /** @@ -50,6 +50,17 @@ public interface UserRepository extends JpaRepository { @Param("searchText") String searchText, Pageable pageable); + Page findAllByAuthority(Authority authority, Pageable pageable); + + Page findByAuthorityAndTenantIdIn(Authority authority, Collection tenantsIds, Pageable pageable); + + @Query("SELECT u FROM UserEntity u INNER JOIN TenantEntity t ON u.tenantId = t.id AND u.authority = :authority " + + "INNER JOIN TenantProfileEntity p ON t.tenantProfileId = p.id " + + "WHERE p.id IN :profiles") + Page findByAuthorityAndTenantProfilesIds(@Param("authority") Authority authority, + @Param("profiles") Collection tenantProfilesIds, + Pageable pageable); + Long countByTenantId(UUID tenantId); } diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultApiLimitService.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/DefaultApiLimitService.java similarity index 81% rename from application/src/main/java/org/thingsboard/server/service/apiusage/DefaultApiLimitService.java rename to dao/src/main/java/org/thingsboard/server/dao/usagerecord/DefaultApiLimitService.java index b12cb4bef3..7a25c70a75 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultApiLimitService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/DefaultApiLimitService.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.apiusage; +package org.thingsboard.server.dao.usagerecord; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.TenantId; @@ -25,7 +26,7 @@ import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileCon import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.dao.usagerecord.ApiLimitService; -import org.thingsboard.server.service.notification.rule.NotificationRuleProcessingService; +import org.thingsboard.server.dao.notification.NotificationRuleProcessingService; @Service @RequiredArgsConstructor @@ -33,7 +34,8 @@ public class DefaultApiLimitService implements ApiLimitService { private final EntityService entityService; private final TbTenantProfileCache tenantProfileCache; - private final NotificationRuleProcessingService notificationRuleProcessingService; + @Autowired(required = false) + private NotificationRuleProcessingService notificationRuleProcessingService; @Override public boolean checkEntitiesLimit(TenantId tenantId, EntityType entityType) { @@ -43,7 +45,9 @@ public class DefaultApiLimitService implements ApiLimitService { EntityTypeFilter filter = new EntityTypeFilter(); filter.setEntityType(entityType); long currentCount = entityService.countEntitiesByQuery(tenantId, null, new EntityCountQuery(filter)); - notificationRuleProcessingService.process(tenantId, entityType, limit, currentCount); + if (notificationRuleProcessingService != null) { + notificationRuleProcessingService.process(tenantId, entityType, limit, currentCount); + } return currentCount < limit; } else { return true; diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java index de1d3dedcf..54d847a26e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java @@ -17,11 +17,14 @@ package org.thingsboard.server.dao.user; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.TenantEntityDao; +import java.util.List; import java.util.UUID; public interface UserDao extends Dao, TenantEntityDao { @@ -79,6 +82,12 @@ public interface UserDao extends Dao, TenantEntityDao { */ PageData findCustomerUsers(UUID tenantId, UUID customerId, PageLink pageLink); - PageData findAll(TenantId tenantId, PageLink pageLink); + PageData findAll(PageLink pageLink); + + PageData findAllByAuthority(Authority authority, PageLink pageLink); + + PageData findByAuthorityAndTenantsIds(Authority authority, List tenantsIds, PageLink pageLink); + + PageData findByAuthorityAndTenantProfilesIds(Authority authority, List tenantProfilesIds, PageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index 4b55cb099b..18f413ab17 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -34,10 +34,12 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.UserCredentialsId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent; import org.thingsboard.server.dao.entity.AbstractEntityService; @@ -46,6 +48,7 @@ import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -250,8 +253,23 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic } @Override - public PageData findAllUsers(TenantId tenantId, PageLink pageLink) { - return userDao.findAll(tenantId, pageLink); + public PageData findAllTenantAdmins(PageLink pageLink) { + return userDao.findAllByAuthority(Authority.TENANT_ADMIN, pageLink); + } + + @Override + public PageData findTenantAdminsByTenantsIds(List tenantsIds, PageLink pageLink) { + return userDao.findByAuthorityAndTenantsIds(Authority.TENANT_ADMIN, tenantsIds, pageLink); + } + + @Override + public PageData findTenantAdminsByTenantProfilesIds(List tenantProfilesIds, PageLink pageLink) { + return userDao.findByAuthorityAndTenantProfilesIds(Authority.TENANT_ADMIN, tenantProfilesIds, pageLink); + } + + @Override + public PageData findAllUsers(PageLink pageLink) { + return userDao.findAll(pageLink); } @Override