Notification api permission checks refactoring

This commit is contained in:
ViacheslavKlimov 2023-02-21 12:36:15 +02:00
parent dd5c970b3a
commit e3f971231a
10 changed files with 95 additions and 68 deletions

View File

@ -25,7 +25,6 @@ import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@ -173,7 +172,6 @@ import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.StringUtils.isNotEmpty; import static org.thingsboard.server.common.data.StringUtils.isNotEmpty;
import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD;
import static org.thingsboard.server.controller.ControllerConstants.INCORRECT_TENANT_ID;
import static org.thingsboard.server.controller.UserController.YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION; import static org.thingsboard.server.controller.UserController.YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION;
import static org.thingsboard.server.dao.service.Validator.validateId; import static org.thingsboard.server.dao.service.Validator.validateId;
@ -603,12 +601,16 @@ public abstract class BaseController {
} }
protected <E extends HasId<I> & HasTenantId, I extends EntityId> E checkEntityId(I entityId, ThrowingBiFunction<TenantId, I, E> findingFunction, Operation operation) throws ThingsboardException { protected <E extends HasId<I> & HasTenantId, I extends EntityId> E checkEntityId(I entityId, ThrowingBiFunction<TenantId, I, E> findingFunction, Operation operation) throws ThingsboardException {
return checkEntityId(Resource.of(entityId.getEntityType()), operation, entityId, findingFunction);
}
protected <E extends HasId<I> & HasTenantId, I extends EntityId> E checkEntityId(Resource resource, Operation operation, I entityId, ThrowingBiFunction<TenantId, I, E> findingFunction) throws ThingsboardException {
try { try {
validateId((UUIDBased) entityId, "Invalid " + entityId.getClass().getSimpleName().toLowerCase()); validateId((UUIDBased) entityId, "Invalid entity id");
SecurityUser user = getCurrentUser(); SecurityUser user = getCurrentUser();
E entity = findingFunction.apply(user.getTenantId(), entityId); E entity = findingFunction.apply(user.getTenantId(), entityId);
checkNotNull(entity, entity.getClass().getSimpleName() + " with id [" + entityId + "] not found"); checkNotNull(entity, entityId.getEntityType() + " with id [" + entityId + "] not found");
accessControlService.checkPermission(user, Resource.of(entityId.getEntityType()), operation, entityId, entity); accessControlService.checkPermission(user, resource, operation, entityId, entity);
return entity; return entity;
} catch (Exception e) { } catch (Exception e) {
throw handleException(e, false); throw handleException(e, false);
@ -665,7 +667,7 @@ public abstract class BaseController {
if (!alarmId.equals(alarmComment.getAlarmId())) { if (!alarmId.equals(alarmComment.getAlarmId())) {
throw new ThingsboardException("Alarm id does not match with comment alarm id", ThingsboardErrorCode.BAD_REQUEST_PARAMS); throw new ThingsboardException("Alarm id does not match with comment alarm id", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
} }
return alarmComment; return alarmComment;
} catch (Exception e) { } catch (Exception e) {
throw handleException(e, false); throw handleException(e, false);
} }

View File

@ -63,10 +63,13 @@ import org.thingsboard.server.service.security.permission.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@RequestMapping("/api") @RequestMapping("/api")
@ -140,6 +143,7 @@ public class NotificationController extends BaseController {
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@RequestParam(defaultValue = "false") boolean unreadOnly, @RequestParam(defaultValue = "false") boolean unreadOnly,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
// no permissions
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationService.findNotificationsByRecipientIdAndReadStatus(user.getTenantId(), user.getId(), unreadOnly, pageLink); return notificationService.findNotificationsByRecipientIdAndReadStatus(user.getTenantId(), user.getId(), unreadOnly, pageLink);
} }
@ -148,6 +152,7 @@ public class NotificationController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
public void markNotificationAsRead(@PathVariable UUID id, public void markNotificationAsRead(@PathVariable UUID id,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) {
// no permissions
NotificationId notificationId = new NotificationId(id); NotificationId notificationId = new NotificationId(id);
notificationCenter.markNotificationAsRead(user.getTenantId(), user.getId(), notificationId); notificationCenter.markNotificationAsRead(user.getTenantId(), user.getId(), notificationId);
} }
@ -155,6 +160,7 @@ public class NotificationController extends BaseController {
@PutMapping("/notifications/read") @PutMapping("/notifications/read")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
public void markAllNotificationsAsRead(@AuthenticationPrincipal SecurityUser user) { public void markAllNotificationsAsRead(@AuthenticationPrincipal SecurityUser user) {
// no permissions
notificationCenter.markAllNotificationsAsRead(user.getTenantId(), user.getId()); notificationCenter.markAllNotificationsAsRead(user.getTenantId(), user.getId());
} }
@ -162,6 +168,7 @@ public class NotificationController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
public void deleteNotification(@PathVariable UUID id, public void deleteNotification(@PathVariable UUID id,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) {
// no permissions
NotificationId notificationId = new NotificationId(id); NotificationId notificationId = new NotificationId(id);
notificationCenter.deleteNotification(user.getTenantId(), user.getId(), notificationId); notificationCenter.deleteNotification(user.getTenantId(), user.getId(), notificationId);
} }
@ -174,7 +181,7 @@ public class NotificationController extends BaseController {
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");
} }
notificationRequest.setTenantId(user.getTenantId()); notificationRequest.setTenantId(user.getTenantId());
checkEntity(notificationRequest.getId(), notificationRequest, Resource.NOTIFICATION_REQUEST); checkEntity(notificationRequest.getId(), notificationRequest, NOTIFICATION);
notificationRequest.setOriginatorEntityId(user.getId()); notificationRequest.setOriginatorEntityId(user.getId());
if (notificationRequest.getInfo() != null && !(notificationRequest.getInfo() instanceof UserOriginatedNotificationInfo)) { if (notificationRequest.getInfo() != null && !(notificationRequest.getInfo() instanceof UserOriginatedNotificationInfo)) {
@ -190,13 +197,15 @@ public class NotificationController extends BaseController {
@PostMapping("/notification/request/preview") @PostMapping("/notification/request/preview")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request, public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
NotificationRequestPreview preview = new NotificationRequestPreview(); NotificationRequestPreview preview = new NotificationRequestPreview();
request.setOriginatorEntityId(user.getId()); request.setOriginatorEntityId(user.getId());
NotificationTemplate template; NotificationTemplate template;
if (request.getTemplateId() != null) { if (request.getTemplateId() != null) {
template = notificationTemplateService.findNotificationTemplateById(user.getTenantId(), request.getTemplateId()); template = notificationTemplateService.findNotificationTemplateById(user.getTenantId(), request.getTemplateId());
checkNotNull(template, "Template not found");
accessControlService.checkPermission(user, NOTIFICATION, Operation.READ, template.getId(), template);
} else { } else {
template = request.getTemplate(); template = request.getTemplate();
} }
@ -222,21 +231,19 @@ public class NotificationController extends BaseController {
})); }));
preview.setProcessedTemplates(processedTemplates); preview.setProcessedTemplates(processedTemplates);
// generic permission
Map<String, Integer> recipientsCountByTarget = new HashMap<>(); Map<String, Integer> recipientsCountByTarget = new HashMap<>();
request.getTargets().forEach(targetId -> { List<NotificationTarget> targets = notificationTargetService.findNotificationTargetsByTenantIdAndIds(user.getTenantId(),
NotificationTarget notificationTarget = notificationTargetService.findNotificationTargetById(user.getTenantId(), new NotificationTargetId(targetId)); request.getTargets().stream().map(NotificationTargetId::new).collect(Collectors.toList()));
if (notificationTarget == null) { for (NotificationTarget target : targets) {
throw new IllegalArgumentException("Notification target with id " + targetId + " not found");
}
int recipientsCount; int recipientsCount;
if (notificationTarget.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) { if (target.getConfiguration().getType() == NotificationTargetType.PLATFORM_USERS) {
recipientsCount = notificationTargetService.countRecipientsForNotificationTargetConfig(user.getTenantId(), notificationTarget.getConfiguration()); recipientsCount = notificationTargetService.countRecipientsForNotificationTargetConfig(user.getTenantId(), target.getConfiguration());
} else { } else {
recipientsCount = 1; recipientsCount = 1;
} }
recipientsCountByTarget.put(notificationTarget.getName(), recipientsCount); recipientsCountByTarget.put(target.getName(), recipientsCount);
}); }
preview.setRecipientsCountByTarget(recipientsCountByTarget); preview.setRecipientsCountByTarget(recipientsCountByTarget);
preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum()); preview.setTotalRecipientsCount(recipientsCountByTarget.values().stream().mapToInt(Integer::intValue).sum());
@ -247,7 +254,7 @@ public class NotificationController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationRequestInfo getNotificationRequestById(@PathVariable UUID id) throws ThingsboardException { public NotificationRequestInfo getNotificationRequestById(@PathVariable UUID id) throws ThingsboardException {
NotificationRequestId notificationRequestId = new NotificationRequestId(id); NotificationRequestId notificationRequestId = new NotificationRequestId(id);
return checkEntityId(notificationRequestId, notificationRequestService::findNotificationRequestInfoById, Operation.READ); return checkEntityId(NOTIFICATION, Operation.READ, notificationRequestId, notificationRequestService::findNotificationRequestInfoById);
} }
@GetMapping("/notification/requests") @GetMapping("/notification/requests")
@ -258,6 +265,7 @@ public class NotificationController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
// generic permission
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationRequestService.findNotificationRequestsInfosByTenantIdAndOriginatorType(user.getTenantId(), EntityType.USER, pageLink); return notificationRequestService.findNotificationRequestsInfosByTenantIdAndOriginatorType(user.getTenantId(), EntityType.USER, pageLink);
} }
@ -266,7 +274,7 @@ public class NotificationController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public void deleteNotificationRequest(@PathVariable UUID id) throws Exception { public void deleteNotificationRequest(@PathVariable UUID id) throws Exception {
NotificationRequestId notificationRequestId = new NotificationRequestId(id); NotificationRequestId notificationRequestId = new NotificationRequestId(id);
NotificationRequest notificationRequest = checkEntityId(notificationRequestId, notificationRequestService::findNotificationRequestById, Operation.DELETE); NotificationRequest notificationRequest = checkEntityId(NOTIFICATION, Operation.DELETE, notificationRequestId, notificationRequestService::findNotificationRequestById);
doDeleteAndLog(EntityType.NOTIFICATION_REQUEST, notificationRequest, notificationCenter::deleteNotificationRequest); doDeleteAndLog(EntityType.NOTIFICATION_REQUEST, notificationRequest, notificationCenter::deleteNotificationRequest);
} }
@ -275,6 +283,7 @@ public class NotificationController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationSettings saveNotificationSettings(@RequestBody @Valid NotificationSettings notificationSettings, public NotificationSettings saveNotificationSettings(@RequestBody @Valid NotificationSettings notificationSettings,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) {
// generic permission
TenantId tenantId = user.isSystemAdmin() ? TenantId.SYS_TENANT_ID : user.getTenantId(); TenantId tenantId = user.isSystemAdmin() ? TenantId.SYS_TENANT_ID : user.getTenantId();
notificationSettingsService.saveNotificationSettings(tenantId, notificationSettings); notificationSettingsService.saveNotificationSettings(tenantId, notificationSettings);
return notificationSettings; return notificationSettings;
@ -283,6 +292,7 @@ public class NotificationController extends BaseController {
@GetMapping("/notification/settings") @GetMapping("/notification/settings")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public NotificationSettings getNotificationSettings(@AuthenticationPrincipal SecurityUser user) { public NotificationSettings getNotificationSettings(@AuthenticationPrincipal SecurityUser user) {
// generic permission
TenantId tenantId = user.isSystemAdmin() ? TenantId.SYS_TENANT_ID : user.getTenantId(); TenantId tenantId = user.isSystemAdmin() ? TenantId.SYS_TENANT_ID : user.getTenantId();
return notificationSettingsService.findNotificationSettings(tenantId); return notificationSettingsService.findNotificationSettings(tenantId);
} }

View File

@ -44,6 +44,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.service.security.permission.Resource.NOTIFICATION;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@RequestMapping("/api/notification") @RequestMapping("/api/notification")
@ -57,7 +59,7 @@ public class NotificationRuleController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
public NotificationRule saveNotificationRule(@RequestBody @Valid NotificationRule notificationRule) throws Exception { public NotificationRule saveNotificationRule(@RequestBody @Valid NotificationRule notificationRule) throws Exception {
notificationRule.setTenantId(getTenantId()); notificationRule.setTenantId(getTenantId());
checkEntity(notificationRule.getId(), notificationRule, Resource.NOTIFICATION_RULE); checkEntity(notificationRule.getId(), notificationRule, NOTIFICATION);
return doSaveAndLog(EntityType.NOTIFICATION_RULE, notificationRule, notificationRuleService::saveNotificationRule); return doSaveAndLog(EntityType.NOTIFICATION_RULE, notificationRule, notificationRuleService::saveNotificationRule);
} }
@ -65,7 +67,7 @@ public class NotificationRuleController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
public NotificationRuleInfo getNotificationRuleById(@PathVariable UUID id) throws ThingsboardException { public NotificationRuleInfo getNotificationRuleById(@PathVariable UUID id) throws ThingsboardException {
NotificationRuleId notificationRuleId = new NotificationRuleId(id); NotificationRuleId notificationRuleId = new NotificationRuleId(id);
return checkEntityId(notificationRuleId, notificationRuleService::findNotificationRuleInfoById, Operation.READ); return checkEntityId(NOTIFICATION, Operation.READ, notificationRuleId, notificationRuleService::findNotificationRuleInfoById);
} }
@GetMapping("/rules") @GetMapping("/rules")
@ -76,6 +78,7 @@ public class NotificationRuleController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
// generic permission
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationRuleService.findNotificationRulesInfosByTenantId(user.getTenantId(), pageLink); return notificationRuleService.findNotificationRulesInfosByTenantId(user.getTenantId(), pageLink);
} }
@ -85,7 +88,7 @@ public class NotificationRuleController extends BaseController {
public void deleteNotificationRule(@PathVariable UUID id, public void deleteNotificationRule(@PathVariable UUID id,
@AuthenticationPrincipal SecurityUser user) throws Exception { @AuthenticationPrincipal SecurityUser user) throws Exception {
NotificationRuleId notificationRuleId = new NotificationRuleId(id); NotificationRuleId notificationRuleId = new NotificationRuleId(id);
NotificationRule notificationRule = checkEntityId(notificationRuleId, notificationRuleService::findNotificationRuleById, Operation.DELETE); NotificationRule notificationRule = checkEntityId(NOTIFICATION, Operation.DELETE, notificationRuleId, notificationRuleService::findNotificationRuleById);
doDeleteAndLog(EntityType.NOTIFICATION_RULE, notificationRule, notificationRuleService::deleteNotificationRuleById); doDeleteAndLog(EntityType.NOTIFICATION_RULE, notificationRule, notificationRuleService::deleteNotificationRuleById);
tbClusterService.broadcastEntityStateChangeEvent(user.getTenantId(), notificationRuleId, ComponentLifecycleEvent.DELETED); tbClusterService.broadcastEntityStateChangeEvent(user.getTenantId(), notificationRuleId, ComponentLifecycleEvent.DELETED);
} }

View File

@ -31,10 +31,15 @@ import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget; 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.NotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.NotificationTargetType; 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.UsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.UsersFilterType;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -51,6 +56,7 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@ -78,17 +84,11 @@ public class NotificationTargetController extends BaseController {
public NotificationTarget saveNotificationTarget(@RequestBody @Valid NotificationTarget notificationTarget, public NotificationTarget saveNotificationTarget(@RequestBody @Valid NotificationTarget notificationTarget,
@AuthenticationPrincipal SecurityUser user) throws Exception { @AuthenticationPrincipal SecurityUser user) throws Exception {
notificationTarget.setTenantId(user.getTenantId()); notificationTarget.setTenantId(user.getTenantId());
checkEntity(notificationTarget.getId(), notificationTarget, Resource.NOTIFICATION_TARGET); checkEntity(notificationTarget.getId(), notificationTarget, NOTIFICATION);
if (!user.isSystemAdmin()) {
NotificationTargetConfig targetConfig = notificationTarget.getConfiguration(); NotificationTargetConfig targetConfig = notificationTarget.getConfiguration();
if (targetConfig.getType() == NotificationTargetType.PLATFORM_USERS) { if (targetConfig.getType() == NotificationTargetType.PLATFORM_USERS) {
PageDataIterable<User> recipients = new PageDataIterable<>(pageLink -> { checkTargetUsers(user, targetConfig);
return notificationTargetService.findRecipientsForNotificationTargetConfig(user.getTenantId(), null, targetConfig, pageLink);
}, 200);
for (User recipient : recipients) {
accessControlService.checkPermission(user, Resource.USER, Operation.READ, recipient.getId(), recipient);
}
}
} }
return doSaveAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::saveNotificationTarget); return doSaveAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::saveNotificationTarget);
@ -101,10 +101,10 @@ public class NotificationTargetController extends BaseController {
@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 {
NotificationTargetId notificationTargetId = new NotificationTargetId(id); NotificationTargetId notificationTargetId = new NotificationTargetId(id);
return checkEntityId(notificationTargetId, notificationTargetService::findNotificationTargetById, Operation.READ); return checkEntityId(NOTIFICATION, Operation.READ, notificationTargetId, notificationTargetService::findNotificationTargetById);
} }
@ApiOperation(value = "Get recipient for notification target config (getRecipientsForNotificationTargetConfig)", @ApiOperation(value = "Get recipients for notification target config (getRecipientsForNotificationTargetConfig)",
notes = "Get the list (page) of recipients (users) for such notification target configuration." + notes = "Get the list (page) of recipients (users) for such notification target configuration." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@PostMapping("/target/recipients") @PostMapping("/target/recipients")
@ -113,20 +113,23 @@ public class NotificationTargetController extends BaseController {
@RequestParam int pageSize, @RequestParam int pageSize,
@RequestParam int page, @RequestParam int page,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, null, null, null); // generic permission
PageData<User> recipients = notificationTargetService.findRecipientsForNotificationTargetConfig(user.getTenantId(), null, notificationTarget.getConfiguration(), pageLink); NotificationTargetConfig targetConfig = notificationTarget.getConfiguration();
if (!user.isSystemAdmin()) { if (targetConfig.getType() == NotificationTargetType.PLATFORM_USERS) {
for (User recipient : recipients.getData()) { checkTargetUsers(user, targetConfig);
accessControlService.checkPermission(user, Resource.USER, Operation.READ, recipient.getId(), recipient); } else {
} throw new IllegalArgumentException("Target type is not platform users");
} }
return recipients;
PageLink pageLink = createPageLink(pageSize, page, null, null, null);
return notificationTargetService.findRecipientsForNotificationTargetConfig(user.getTenantId(), null, notificationTarget.getConfiguration(), pageLink);
} }
@GetMapping(value = "/targets", params = {"ids"}) @GetMapping(value = "/targets", params = {"ids"})
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public List<NotificationTarget> getNotificationTargetsByIds(@RequestParam("ids") UUID[] ids, public List<NotificationTarget> getNotificationTargetsByIds(@RequestParam("ids") UUID[] ids,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) {
// generic permission
List<NotificationTargetId> targetsIds = Arrays.stream(ids).map(NotificationTargetId::new).collect(Collectors.toList()); List<NotificationTargetId> targetsIds = Arrays.stream(ids).map(NotificationTargetId::new).collect(Collectors.toList());
return notificationTargetService.findNotificationTargetsByTenantIdAndIds(user.getTenantId(), targetsIds); return notificationTargetService.findNotificationTargetsByTenantIdAndIds(user.getTenantId(), targetsIds);
} }
@ -142,6 +145,7 @@ public class NotificationTargetController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
// generic permission
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return notificationTargetService.findNotificationTargetsByTenantId(user.getTenantId(), pageLink); return notificationTargetService.findNotificationTargetsByTenantId(user.getTenantId(), pageLink);
} }
@ -154,8 +158,27 @@ public class NotificationTargetController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public void deleteNotificationTargetById(@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(NOTIFICATION, Operation.DELETE, notificationTargetId, notificationTargetService::findNotificationTargetById);
doDeleteAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::deleteNotificationTargetById); doDeleteAndLog(EntityType.NOTIFICATION_TARGET, notificationTarget, notificationTargetService::deleteNotificationTargetById);
} }
private void checkTargetUsers(SecurityUser user, NotificationTargetConfig targetConfig) throws ThingsboardException {
if (user.isSystemAdmin()) {
return;
}
// generic permission for users
UsersFilter usersFilter = ((PlatformUsersNotificationTargetConfig) targetConfig).getUsersFilter();
if (usersFilter.getType() == UsersFilterType.USER_LIST) {
PageDataIterable<User> recipients = new PageDataIterable<>(pageLink -> {
return notificationTargetService.findRecipientsForNotificationTargetConfig(user.getTenantId(), null, targetConfig, pageLink);
}, 200);
for (User recipient : recipients) {
accessControlService.checkPermission(user, Resource.USER, Operation.READ, recipient.getId(), recipient);
}
} else if (usersFilter.getType() == UsersFilterType.CUSTOMER_USERS) {
CustomerId customerId = new CustomerId(((CustomerUsersFilter) usersFilter).getCustomerId());
checkEntityId(customerId, Operation.READ);
}
}
} }

View File

@ -52,6 +52,7 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.service.security.permission.Resource.NOTIFICATION;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@ -82,7 +83,7 @@ public class NotificationTemplateController extends BaseController {
@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 {
notificationTemplate.setTenantId(getTenantId()); notificationTemplate.setTenantId(getTenantId());
checkEntity(notificationTemplate.getId(), notificationTemplate, Resource.NOTIFICATION_TEMPLATE); checkEntity(notificationTemplate.getId(), notificationTemplate, NOTIFICATION);
return doSaveAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::saveNotificationTemplate); return doSaveAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::saveNotificationTemplate);
} }
@ -93,7 +94,7 @@ public class NotificationTemplateController extends BaseController {
@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 {
NotificationTemplateId notificationTemplateId = new NotificationTemplateId(id); NotificationTemplateId notificationTemplateId = new NotificationTemplateId(id);
return checkEntityId(notificationTemplateId, notificationTemplateService::findNotificationTemplateById, Operation.READ); return checkEntityId(NOTIFICATION, Operation.READ, notificationTemplateId, notificationTemplateService::findNotificationTemplateById);
} }
@ApiOperation(value = "Get notification templates (getNotificationTemplates)", @ApiOperation(value = "Get notification templates (getNotificationTemplates)",
@ -108,6 +109,7 @@ public class NotificationTemplateController extends BaseController {
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@RequestParam(required = false) NotificationType[] notificationTypes, @RequestParam(required = false) NotificationType[] notificationTypes,
@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { @AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
// generic permission
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (notificationTypes == null || notificationTypes.length == 0) { if (notificationTypes == null || notificationTypes.length == 0) {
notificationTypes = NotificationType.values(); notificationTypes = NotificationType.values();
@ -124,7 +126,7 @@ public class NotificationTemplateController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public void deleteNotificationTemplateById(@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(NOTIFICATION, Operation.DELETE, notificationTemplateId, notificationTemplateService::findNotificationTemplateById);
doDeleteAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::deleteNotificationTemplateById); doDeleteAndLog(EntityType.NOTIFICATION_TEMPLATE, notificationTemplate, notificationTemplateService::deleteNotificationTemplateById);
} }
@ -136,6 +138,7 @@ public class NotificationTemplateController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
public List<SlackConversation> listSlackConversations(@RequestParam SlackConversationType type, public List<SlackConversation> listSlackConversations(@RequestParam SlackConversationType type,
@AuthenticationPrincipal SecurityUser user) { @AuthenticationPrincipal SecurityUser user) {
// generic permission
NotificationSettings settings = notificationSettingsService.findNotificationSettings(user.getTenantId()); NotificationSettings settings = notificationSettingsService.findNotificationSettings(user.getTenantId());
SlackNotificationDeliveryMethodConfig slackConfig = (SlackNotificationDeliveryMethodConfig) SlackNotificationDeliveryMethodConfig slackConfig = (SlackNotificationDeliveryMethodConfig)
settings.getDeliveryMethodsConfigs().get(NotificationDeliveryMethod.SLACK); settings.getDeliveryMethodsConfigs().get(NotificationDeliveryMethod.SLACK);

View File

@ -107,15 +107,8 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
} }
if (notificationTemplate == null) throw new IllegalArgumentException("Template is missing"); if (notificationTemplate == null) throw new IllegalArgumentException("Template is missing");
List<NotificationTarget> targets = notificationRequest.getTargets().stream() List<NotificationTarget> targets = notificationTargetService.findNotificationTargetsByTenantIdAndIds(tenantId,
.map(NotificationTargetId::new) notificationRequest.getTargets().stream().map(NotificationTargetId::new).collect(Collectors.toList()));
.map(targetId -> notificationTargetService.findNotificationTargetById(tenantId, targetId))
.peek(target -> {
if (target == null) {
throw new IllegalArgumentException("Some of the targets no longer exist");
}
})
.collect(Collectors.toList());
notificationTemplate.getConfiguration().getDeliveryMethodsTemplates().forEach((deliveryMethod, template) -> { notificationTemplate.getConfiguration().getDeliveryMethodsTemplates().forEach((deliveryMethod, template) -> {
if (!template.isEnabled()) return; if (!template.isEnabled()) return;

View File

@ -44,10 +44,7 @@ public enum Resource {
RPC(EntityType.RPC), RPC(EntityType.RPC),
QUEUE(EntityType.QUEUE), QUEUE(EntityType.QUEUE),
VERSION_CONTROL, VERSION_CONTROL,
NOTIFICATION_TARGET(EntityType.NOTIFICATION_TARGET), NOTIFICATION;
NOTIFICATION_TEMPLATE(EntityType.NOTIFICATION_TEMPLATE),
NOTIFICATION_REQUEST(EntityType.NOTIFICATION_REQUEST),
NOTIFICATION_RULE(EntityType.NOTIFICATION_RULE);
private final EntityType entityType; private final EntityType entityType;

View File

@ -40,9 +40,7 @@ public class SysAdminPermissions extends AbstractPermissions {
put(Resource.TENANT_PROFILE, PermissionChecker.allowAllPermissionChecker); put(Resource.TENANT_PROFILE, PermissionChecker.allowAllPermissionChecker);
put(Resource.TB_RESOURCE, systemEntityPermissionChecker); put(Resource.TB_RESOURCE, systemEntityPermissionChecker);
put(Resource.QUEUE, systemEntityPermissionChecker); put(Resource.QUEUE, systemEntityPermissionChecker);
put(Resource.NOTIFICATION_TARGET, systemEntityPermissionChecker); put(Resource.NOTIFICATION, systemEntityPermissionChecker);
put(Resource.NOTIFICATION_TEMPLATE, systemEntityPermissionChecker);
put(Resource.NOTIFICATION_REQUEST, systemEntityPermissionChecker);
} }
private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker() { private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker() {

View File

@ -49,10 +49,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
put(Resource.RPC, tenantEntityPermissionChecker); put(Resource.RPC, tenantEntityPermissionChecker);
put(Resource.QUEUE, queuePermissionChecker); put(Resource.QUEUE, queuePermissionChecker);
put(Resource.VERSION_CONTROL, PermissionChecker.allowAllPermissionChecker); put(Resource.VERSION_CONTROL, PermissionChecker.allowAllPermissionChecker);
put(Resource.NOTIFICATION_TARGET, tenantEntityPermissionChecker); put(Resource.NOTIFICATION, tenantEntityPermissionChecker);
put(Resource.NOTIFICATION_TEMPLATE, tenantEntityPermissionChecker);
put(Resource.NOTIFICATION_REQUEST, tenantEntityPermissionChecker);
put(Resource.NOTIFICATION_RULE, tenantEntityPermissionChecker);
} }
public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker() { public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker() {

View File

@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -46,7 +47,7 @@ import java.util.UUID;
public class NotificationRequest extends BaseData<NotificationRequestId> implements HasTenantId, HasName { public class NotificationRequest extends BaseData<NotificationRequestId> implements HasTenantId, HasName {
private TenantId tenantId; private TenantId tenantId;
@NotNull @NotEmpty
private List<UUID> targets; private List<UUID> targets;
private NotificationTemplateId templateId; private NotificationTemplateId templateId;