From ca1f1e56866f4ad2af02d998c390f6f750eaec5a Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 13 Nov 2025 14:49:04 +0200 Subject: [PATCH] Fix api key permissions --- .../server/controller/ApiKeyController.java | 5 +++++ .../permission/CustomerUserPermissions.java | 2 +- .../security/permission/SysAdminPermissions.java | 13 ++++++++++++- .../security/permission/TenantAdminPermissions.java | 1 - .../server/common/data/pat/ApiKeyInfo.java | 2 ++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java b/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java index d9df135811..4078f7855f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ApiKeyController.java @@ -76,6 +76,7 @@ public class ApiKeyController extends BaseController { SecurityUser securityUser = getCurrentUser(); apiKeyInfo.setTenantId(securityUser.getTenantId()); checkEntity(apiKeyInfo.getId(), apiKeyInfo, Resource.API_KEY); + checkUserId(apiKeyInfo.getUserId(), Operation.WRITE); return checkNotNull(apiKeyService.saveApiKey(securityUser.getTenantId(), apiKeyInfo)); } @@ -101,6 +102,7 @@ public class ApiKeyController extends BaseController { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); UserId userId = new UserId(toUUID(userIdStr)); accessControlService.checkPermission(securityUser, Resource.API_KEY, Operation.READ); + checkUserId(userId, Operation.READ); return apiKeyService.findApiKeysByUserId(securityUser.getTenantId(), userId, pageLink); } @@ -117,6 +119,7 @@ public class ApiKeyController extends BaseController { @RequestBody Optional description) throws Exception { ApiKeyId apiKeyId = new ApiKeyId(id); ApiKey apiKey = checkApiKeyId(apiKeyId, Operation.WRITE); + checkUserId(apiKey.getUserId(), Operation.WRITE); apiKey.setDescription(description.orElse(null)); return apiKeyService.saveApiKey(apiKey.getTenantId(), apiKey); } @@ -132,6 +135,7 @@ public class ApiKeyController extends BaseController { @PathVariable(value = "enabledValue") Boolean enabledValue) throws ThingsboardException { ApiKeyId apiKeyId = new ApiKeyId(id); ApiKey apiKey = checkApiKeyId(apiKeyId, Operation.WRITE); + checkUserId(apiKey.getUserId(), Operation.WRITE); apiKey.setEnabled(enabledValue); return apiKeyService.saveApiKey(apiKey.getTenantId(), apiKey); } @@ -143,6 +147,7 @@ public class ApiKeyController extends BaseController { public void deleteApiKey(@PathVariable UUID id) throws ThingsboardException { ApiKeyId apiKeyId = new ApiKeyId(id); ApiKey apiKey = checkApiKeyId(apiKeyId, Operation.DELETE); + checkUserId(apiKey.getUserId(), Operation.WRITE); apiKeyService.deleteApiKey(apiKey.getTenantId(), apiKey, false); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java index a126bad2c1..8fc1bc3bf0 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java @@ -211,7 +211,7 @@ public class CustomerUserPermissions extends AbstractPermissions { @Override @SuppressWarnings("unchecked") public boolean hasPermission(SecurityUser user, Operation operation, ApiKeyId entityId, ApiKeyInfo entity) { - return user.getTenantId().equals(entity.getTenantId()) && user.getId().equals(entity.getUserId()); + return user.getTenantId().equals(entity.getTenantId()); } }; diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java index 46fdd9a0bb..64c7ad2808 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/SysAdminPermissions.java @@ -18,8 +18,10 @@ package org.thingsboard.server.service.security.permission; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.id.ApiKeyId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.pat.ApiKeyInfo; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.service.security.model.SecurityUser; @@ -45,7 +47,7 @@ public class SysAdminPermissions extends AbstractPermissions { put(Resource.QUEUE, systemEntityPermissionChecker); put(Resource.NOTIFICATION, systemEntityPermissionChecker); put(Resource.MOBILE_APP_SETTINGS, PermissionChecker.allowAllPermissionChecker); - put(Resource.API_KEY, systemEntityPermissionChecker); + put(Resource.API_KEY, PermissionChecker.allowAllPermissionChecker); } private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker() { @@ -72,4 +74,13 @@ public class SysAdminPermissions extends AbstractPermissions { }; + private static final PermissionChecker apiKeysPermissionChecker = new PermissionChecker<>() { + + @Override + public boolean hasPermission(SecurityUser user, Operation operation) { + return true; + } + + }; + } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java index 6e6ebd5cc0..68e0caa520 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java @@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.AiModelId; import org.thingsboard.server.common.data.id.ApiKeyId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.common.data.pat.ApiKey; import org.thingsboard.server.common.data.pat.ApiKeyInfo; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/pat/ApiKeyInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/pat/ApiKeyInfo.java index aea83e5dca..770f4e64f6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/pat/ApiKeyInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/pat/ApiKeyInfo.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.pat; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; @@ -47,6 +48,7 @@ public class ApiKeyInfo extends BaseData implements HasTenantId { private long expirationTime; @NoXss + @NotBlank @Length(fieldName = "description") @Schema(description = "Api Key description.", example = "Api Key description") private String description;