From aff9b5ac25fe7be3b064bd89bf0e0e883a0821ab Mon Sep 17 00:00:00 2001 From: Artem Barysh Date: Mon, 17 Nov 2025 16:57:08 +0200 Subject: [PATCH 1/7] new endpoints --- .../controller/AssetProfileController.java | 34 +++++++++++++++ .../server/controller/CustomerController.java | 35 +++++++++++++++ .../controller/DashboardController.java | 40 +++++++++++++---- .../controller/DeviceProfileController.java | 33 ++++++++++++++ .../controller/RuleChainController.java | 31 +++++++++++++ .../server/controller/TenantController.java | 32 ++++++++++++++ .../controller/TenantProfileController.java | 1 - .../server/controller/UserController.java | 30 +++++++++++++ .../controller/WidgetsBundleController.java | 38 ++++++++++++++++ .../permission/AccessControlService.java | 2 + .../DefaultAccessControlService.java | 10 +++++ .../permission/PermissionChecker.java | 1 + .../AssetProfileControllerTest.java | 36 ++++++++++++++++ .../controller/CustomerControllerTest.java | 39 +++++++++++++++++ .../controller/DashboardControllerTest.java | 39 +++++++++++++++++ .../DeviceProfileControllerTest.java | 40 +++++++++++++++++ .../controller/RuleChainControllerTest.java | 43 +++++++++++++++++++ .../controller/TenantControllerTest.java | 38 ++++++++++++++++ .../TenantProfileControllerTest.java | 41 ++++++++++++++++++ .../server/controller/UserControllerTest.java | 35 +++++++++++++++ .../WidgetsBundleControllerTest.java | 36 ++++++++++++++++ .../server/dao/asset/AssetProfileService.java | 3 ++ .../server/dao/customer/CustomerService.java | 3 ++ .../dao/dashboard/DashboardService.java | 2 + .../dao/device/DeviceProfileService.java | 3 ++ .../server/dao/rule/RuleChainService.java | 2 + .../server/dao/tenant/TenantService.java | 2 + .../server/dao/user/UserService.java | 3 ++ .../dao/widget/WidgetsBundleService.java | 5 +++ .../server/common/data/DeviceProfileInfo.java | 2 +- .../common/data/asset/AssetProfileInfo.java | 3 +- .../server/dao/asset/AssetProfileDao.java | 3 ++ .../dao/asset/AssetProfileServiceImpl.java | 11 +++++ .../server/dao/customer/CustomerDao.java | 4 ++ .../dao/customer/CustomerServiceImpl.java | 10 +++++ .../dao/dashboard/DashboardInfoDao.java | 4 ++ .../dao/dashboard/DashboardServiceImpl.java | 9 ++++ .../server/dao/device/DeviceProfileDao.java | 3 ++ .../dao/device/DeviceProfileServiceImpl.java | 11 +++++ .../server/dao/rule/BaseRuleChainService.java | 9 ++++ .../server/dao/rule/RuleChainDao.java | 4 ++ .../dao/sql/asset/AssetProfileRepository.java | 6 +++ .../dao/sql/asset/JpaAssetProfileDao.java | 6 +++ .../dao/sql/customer/CustomerRepository.java | 2 + .../dao/sql/customer/JpaCustomerDao.java | 6 +++ .../dashboard/DashboardInfoRepository.java | 3 ++ .../sql/dashboard/JpaDashboardInfoDao.java | 6 +++ .../sql/device/DeviceProfileRepository.java | 5 +++ .../dao/sql/device/JpaDeviceProfileDao.java | 6 +++ .../server/dao/sql/rule/JpaRuleChainDao.java | 6 +++ .../dao/sql/rule/RuleChainRepository.java | 3 ++ .../server/dao/sql/tenant/JpaTenantDao.java | 6 +++ .../dao/sql/tenant/TenantRepository.java | 2 + .../server/dao/sql/user/JpaUserDao.java | 6 +++ .../server/dao/sql/user/UserRepository.java | 3 ++ .../dao/sql/widget/JpaWidgetsBundleDao.java | 12 ++++++ .../sql/widget/WidgetsBundleRepository.java | 12 ++++++ .../server/dao/tenant/TenantDao.java | 3 ++ .../server/dao/tenant/TenantServiceImpl.java | 9 ++++ .../thingsboard/server/dao/user/UserDao.java | 4 ++ .../server/dao/user/UserServiceImpl.java | 10 +++++ .../server/dao/widget/WidgetsBundleDao.java | 6 +++ .../dao/widget/WidgetsBundleServiceImpl.java | 20 +++++++++ 63 files changed, 861 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index 96b846eefa..9415e7194e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -16,11 +16,13 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -45,7 +47,10 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutionException; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID_PARAM_DESCRIPTION; @@ -222,4 +227,33 @@ public class AssetProfileController extends BaseController { return checkNotNull(assetProfileService.findAssetProfileNamesByTenantId(tenantId, activeOnly)); } + @ApiOperation(value = "Get Asset Profiles By Ids (getAssetProfilesByIds)", + notes = "Requested asset profiles must be owned by tenant which is performing the request. " + + NEW_LINE) + @PreAuthorize("hasAuthority('TENANT_ADMIN')") + @GetMapping(value = "/assetProfileInfos", params = {"assetProfileIds"}) + public List getAssetProfilesByIds( + @Parameter(description = "A list of asset profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("assetProfileIds") String[] strAssetProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("assetProfileIds", strAssetProfileIds); + + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List assetProfileIds = new ArrayList<>(); + for (String strAssetProfileId : strAssetProfileIds) { + assetProfileIds.add(new AssetProfileId(toUUID(strAssetProfileId))); + } + + return Objects.requireNonNull(checkNotNull(assetProfileService.findAssetProfilesByIdsAsync(tenantId, assetProfileIds).get())) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(user, Resource.ASSET_PROFILE, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index 03ac9c60fa..e0f8cef1c8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -18,10 +18,12 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -40,9 +42,15 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.customer.TbCustomerService; +import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_TEXT_SEARCH_DESCRIPTION; @@ -183,4 +191,31 @@ public class CustomerController extends BaseController { return checkNotNull(customerService.findCustomerByTenantIdAndTitle(tenantId, customerTitle), "Customer with title [" + customerTitle + "] is not found"); } + @ApiOperation(value = "Get customers by Customer Ids (getCustomersByIds)", + notes = "Returns a list of Customer objects based on the provided ids." + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @GetMapping(value = "/customers", params = {"customerIds"}) + public List getCustomersByIds( + @Parameter(description = "A list of customer ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("customerIds") String[] strCustomerIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("customerIds", strCustomerIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List customerIds = new ArrayList<>(); + for (String strCustomerId : strCustomerIds) { + customerIds.add(new CustomerId(toUUID(strCustomerId))); + } + return Objects.requireNonNull(checkNotNull(customerService.findCustomersByTenantIdAndIdsAsync(tenantId, customerIds).get())) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(user, Resource.CUSTOMER, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index 0e3fde0031..f23c3d3e19 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -18,6 +18,7 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; @@ -64,10 +65,12 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @@ -604,14 +607,7 @@ public class DashboardController extends BaseController { checkEdgeId(edgeId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageData nonFilteredResult = dashboardService.findDashboardsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); - List filteredDashboards = nonFilteredResult.getData().stream().filter(dashboardInfo -> { - try { - accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, Operation.READ, dashboardInfo.getId(), dashboardInfo); - return true; - } catch (ThingsboardException e) { - return false; - } - }).collect(Collectors.toList()); + List filteredDashboards = filterDashboardsByReadPermission(nonFilteredResult.getData()); PageData filteredResult = new PageData<>(filteredDashboards, nonFilteredResult.getTotalPages(), nonFilteredResult.getTotalElements(), @@ -619,6 +615,24 @@ public class DashboardController extends BaseController { return checkNotNull(filteredResult); } + @ApiOperation(value = "Get dashboards by Dashboard Ids (getDashboardsByIds)", + notes = "Returns a list of DashboardInfo objects based on the provided ids. " + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @GetMapping(value = "/dashboards", params = {"dashboardIds"}) + public List getDashboardsByIds(@Parameter(description = "A list of dashboard ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("dashboardIds") String[] strDashboardIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("dashboardIds", strDashboardIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List dashboardIds = new ArrayList<>(); + for (String strDashboardId : strDashboardIds) { + dashboardIds.add(new DashboardId(toUUID(strDashboardId))); + } + List dashboards = checkNotNull(dashboardService.findDashboardInfoByIdsAsync(tenantId, dashboardIds).get()); + return filterDashboardsByReadPermission(dashboards); + } + private Set customerIdFromStr(String[] strCustomerIds) { Set customerIds = new HashSet<>(); if (strCustomerIds != null) { @@ -629,4 +643,14 @@ public class DashboardController extends BaseController { return customerIds; } + private List filterDashboardsByReadPermission(List dashboards) { + return dashboards.stream().filter(dashboard -> { + try { + return accessControlService.hasPermission(getCurrentUser(), Resource.DASHBOARD, Operation.READ, dashboard.getId(), dashboard); + } catch (ThingsboardException e) { + return false; + } + }).collect(Collectors.toList()); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index 07f25cd14d..7f6f6bfa61 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -16,12 +16,14 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -48,8 +50,11 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.UUID; +import java.util.concurrent.ExecutionException; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_DATA; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID; @@ -278,4 +283,32 @@ public class DeviceProfileController extends BaseController { return checkNotNull(deviceProfileService.findDeviceProfileNamesByTenantId(tenantId, activeOnly)); } + @ApiOperation(value = "Get Device Profiles By Ids (getDeviceProfilesByIds)", + notes = "Requested device profiles must be owned by tenant which is performing the request. " + + NEW_LINE) + @PreAuthorize("hasAuthority('TENANT_ADMIN')") + @GetMapping(value = "/deviceProfileInfos", params = {"deviceProfileIds"}) + public List getDeviceProfilesByIds( + @Parameter(description = "A list of device profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("deviceProfileIds") String[] strDeviceProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("deviceProfileIds", strDeviceProfileIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List deviceProfileIds = new ArrayList<>(); + for (String strDeviceProfileId : strDeviceProfileIds) { + deviceProfileIds.add(new DeviceProfileId(toUUID(strDeviceProfileId))); + } + + return Objects.requireNonNull(checkNotNull(deviceProfileService.findDeviceProfilesByIdsAsync(tenantId, deviceProfileIds).get())) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(user, Resource.DEVICE_PROFILE, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index efe3e61893..4349ea22bf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -71,12 +72,14 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.rule.TbRuleChainService; import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; import org.thingsboard.server.service.script.RuleNodeTbelScriptEngine; +import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentMap; @@ -90,6 +93,7 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIG import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END; import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_START; +import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; @@ -579,4 +583,31 @@ public class RuleChainController extends BaseController { return checkNotNull(result); } + @ApiOperation(value = "Get Rule Chains By Ids (getRuleChainsByIds)", + notes = "Requested rule chains must be owned by tenant which is performing the request. " + + NEW_LINE) + @PreAuthorize("hasAuthority('TENANT_ADMIN')") + @GetMapping(value = "/ruleChains", params = {"ruleChainIds"}) + public List getRuleChainsByIds( + @Parameter(description = "A list of rule chain ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("ruleChainIds") String[] strRuleChainIds) throws Exception { + checkArrayParameter("ruleChainIds", strRuleChainIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List ruleChainIds = new ArrayList<>(); + for (String strRuleChainId : strRuleChainIds) { + ruleChainIds.add(new RuleChainId(toUUID(strRuleChainId))); + } + return Objects.requireNonNull(checkNotNull(ruleChainService.findRuleChainsByIdsAsync(tenantId, ruleChainIds).get())) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(user, Resource.RULE_CHAIN, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantController.java b/application/src/main/java/org/thingsboard/server/controller/TenantController.java index 3ded7b7171..22ceb33b8d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantController.java @@ -16,11 +16,13 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -39,9 +41,15 @@ import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.tenant.TbTenantService; +import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutionException; + import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; @@ -166,4 +174,28 @@ public class TenantController extends BaseController { return checkNotNull(tenantService.findTenantInfos(pageLink)); } + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @GetMapping(value = "/tenants", params = {"tenantIds"}) + public List getTenantsByIds( + @Parameter(description = "A list of tenant ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string"))) + @RequestParam("tenantIds") String[] strTenantIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("tenantIds", strTenantIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List tenantIds = new ArrayList<>(); + for (String strTenantId : strTenantIds) { + tenantIds.add(new TenantId(toUUID(strTenantId))); + } + return Objects.requireNonNull(checkNotNull(tenantService.findTenantsByIdsAsync(tenantId, tenantIds).get())) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(user, Resource.TENANT, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java b/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java index 1a3bdce1f6..71c8e1e4bc 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java @@ -264,5 +264,4 @@ public class TenantProfileController extends BaseController { return tenantProfileService.findTenantProfilesByIds(TenantId.SYS_TENANT_ID, ids); } - } 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 a2a7c993e9..e0adf27a97 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -84,6 +85,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; @@ -593,6 +597,32 @@ public class UserController extends BaseController { userService.removeMobileSession(user.getTenantId(), mobileToken); } + @ApiOperation(value = "Get Users By Ids (getUsersByIds)", + notes = "Requested users must be owned by tenant or assigned to customer which user is performing the request. ") + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @GetMapping(value = "/users", params = {"userIds"}) + public List getUsersByIds( + @Parameter(description = "A list of user ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("userIds") String[] strUserIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("userIds", strUserIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List userIds = new ArrayList<>(); + for (String strUserId : strUserIds) { + userIds.add(new UserId(toUUID(strUserId))); + } + return Objects.requireNonNull(checkNotNull(userService.findUsersByTenantIdAndIdsAsync(tenantId, userIds).get())) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(user, Resource.USER, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + private void checkNotReserved(String strType, UserSettingsType type) throws ThingsboardException { if (type.isReserved()) { throw new ThingsboardException("Settings with type: " + strType + " are reserved for internal use!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 7c3133d6d9..1060c7fe94 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -16,10 +16,12 @@ package org.thingsboard.server.controller; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -45,13 +47,17 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; +import java.util.Objects; import java.util.Set; +import java.util.concurrent.ExecutionException; import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER; import static org.thingsboard.server.controller.ControllerConstants.INLINE_IMAGES; import static org.thingsboard.server.controller.ControllerConstants.INLINE_IMAGES_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; @@ -234,4 +240,36 @@ public class WidgetsBundleController extends BaseController { } } + @ApiOperation(value = "Get Widgets Bundles By Ids (getWidgetsBundlesByIds)", + notes = "Requested widgets bundles must be system level or owned by tenant of the user which is performing the request. " + + NEW_LINE) + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @GetMapping(value = "/widgetsBundles", params = {"widgetsBundleIds"}) + public List getWidgetsBundlesByIds( + @Parameter(description = "A list of widgets bundle ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("widgetsBundleIds") String[] strWidgetsBundleIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("widgetsBundleIds", strWidgetsBundleIds); + List widgetsBundleIds = new ArrayList<>(); + for (String strWidgetsBundleId : strWidgetsBundleIds) { + widgetsBundleIds.add(new WidgetsBundleId(toUUID(strWidgetsBundleId))); + } + List result; + if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { + result = checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get()); + } else { + result = checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get()); + } + + return Objects.requireNonNull(result) + .stream() + .filter(e -> { + try { + return accessControlService.hasPermission(getCurrentUser(), Resource.WIDGETS_BUNDLE, Operation.READ, e.getId(), e); + } catch (ThingsboardException ex) { + return false; + } + }) + .toList(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java index 9f693877cd..b760a54ade 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java @@ -26,4 +26,6 @@ public interface AccessControlService { void checkPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException; + boolean hasPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException; + } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java index a5feb1c502..9bf05e2d73 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java @@ -65,6 +65,16 @@ public class DefaultAccessControlService implements AccessControlService { } } + @Override + @SuppressWarnings("unchecked") + public boolean hasPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException { + PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); + if (permissionChecker != null) { + return permissionChecker.hasPermission(user, operation, entityId, entity); + } + return false; + } + private PermissionChecker getPermissionChecker(Authority authority, Resource resource) throws ThingsboardException { Permissions permissions = authorityPermissions.get(authority); if (permissions == null) { diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java b/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java index 2fcf6b71fc..216d74fe2f 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java @@ -16,6 +16,7 @@ package org.thingsboard.server.service.security.permission; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java index 2691352d01..14ac8c91d1 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java @@ -46,9 +46,13 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; import java.util.stream.Collectors; import static org.hamcrest.Matchers.containsString; @@ -195,6 +199,38 @@ public class AssetProfileControllerTest extends AbstractControllerTest { Assert.assertEquals(savedAssetProfile.getName(), foundAssetProfileInfo.getName()); } + @Test + public void testFindAssetProfileInfoByIds() throws Exception { + List assetProfiles = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + AssetProfile assetProfile = this.createAssetProfile("Asset Profile" + i); + assetProfile.setTenantId(savedTenant.getId()); + assetProfiles.add(doPost("/api/assetProfile", assetProfile, AssetProfileInfo.class)); + } + + List expected = assetProfiles.subList(5, 15); + + String idsParam = expected.stream() + .map(ap -> ap.getId().getId().toString()) + .collect(Collectors.joining(",")); + AssetProfileInfo[] foundAssetProfileInfos = doGet("/api/assetProfileInfos?assetProfileIds=" + idsParam, AssetProfileInfo[].class); + + Assert.assertNotNull(foundAssetProfileInfos); + Assert.assertEquals(expected.size(), foundAssetProfileInfos.length); + + Map infoById = Arrays.stream(foundAssetProfileInfos) + .collect(Collectors.toMap(info -> info.getId().getId(), Function.identity())); + + for (AssetProfileInfo assetProfileInfo : expected) { + UUID id = assetProfileInfo.getId().getId(); + AssetProfileInfo info = infoById.get(id); + Assert.assertNotNull("AssetProfileInfo not found for id " + id, info); + + Assert.assertEquals(assetProfileInfo.getId(), info.getId()); + Assert.assertEquals(assetProfileInfo.getName(), info.getName()); + } + } + @Test public void whenGetAssetProfileInfoById_thenPermissionsAreChecked() throws Exception { AssetProfile assetProfile = createAssetProfile("Asset profile 1"); diff --git a/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java index f312e49f71..6e97e1cb99 100644 --- a/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java @@ -47,8 +47,13 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.containsString; @@ -260,6 +265,40 @@ public class CustomerControllerTest extends AbstractControllerTest { .andExpect(status().isOk()); } + @Test + public void testFindCustomersByIds() throws Exception { + List savedCustomers = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + Customer customer = new Customer(); + customer.setTitle("My customer " + i); + savedCustomers.add(doPost("/api/customer", customer, Customer.class)); + } + + String idsParam = savedCustomers.stream() + .map(c -> c.getId().getId().toString()) + .collect(Collectors.joining(",")); + + Customer[] foundCustomers = doGet("/api/customers?customerIds=" + idsParam, Customer[].class); + + Assert.assertNotNull(foundCustomers); + Assert.assertEquals(savedCustomers.size(), foundCustomers.length); + + Map foundById = Arrays.stream(foundCustomers) + .collect(Collectors.toMap(c -> c.getId().getId(), Function.identity())); + + for (Customer savedCustomer : savedCustomers) { + UUID id = savedCustomer.getId().getId(); + Customer foundCustomer = foundById.get(id); + Assert.assertNotNull("Customer not found for id " + id, foundCustomer); + Assert.assertEquals(savedCustomer, foundCustomer); + } + + for (Customer savedCustomer : savedCustomers) { + doDelete("/api/customer/" + savedCustomer.getId().getId().toString()) + .andExpect(status().isOk()); + } + } + @Test public void testDeleteCustomer() throws Exception { Customer customer = new Customer(); diff --git a/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java index a73bc3befb..052ff8777b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java @@ -55,9 +55,12 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Map; +import java.util.UUID; +import java.util.function.Function; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -155,6 +158,42 @@ public class DashboardControllerTest extends AbstractControllerTest { Assert.assertEquals(savedDashboard, foundDashboard); } + @Test + public void testFindDashboardInfosByIds() throws Exception { + List dashboards = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + Dashboard dashboard = new Dashboard(); + dashboard.setTitle("My dashboard " + i); + dashboards.add(doPost("/api/dashboard", dashboard, Dashboard.class)); + } + + List expected = dashboards.subList(5, 15); + + String idsParam = expected.stream() + .map(d -> d.getId().getId().toString()) + .collect(Collectors.joining(",")); + + DashboardInfo[] result = doGet( + "/api/dashboards?dashboardIds=" + idsParam, + DashboardInfo[].class + ); + + Assert.assertNotNull(result); + Assert.assertEquals(expected.size(), result.length); + + Map infoById = Arrays.stream(result) + .collect(Collectors.toMap(info -> info.getId().getId(), Function.identity())); + + for (Dashboard dashboard : expected) { + UUID id = dashboard.getId().getId(); + DashboardInfo info = infoById.get(id); + Assert.assertNotNull("DashboardInfo not found for id " + id, info); + + Assert.assertEquals(dashboard.getId(), info.getId()); + Assert.assertEquals(dashboard.getTitle(), info.getTitle()); + } + } + @Test public void testDeleteDashboard() throws Exception { Dashboard dashboard = new Dashboard(); diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java index 320e3815f6..fb0e3fb57a 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java @@ -56,9 +56,13 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -214,6 +218,42 @@ public class DeviceProfileControllerTest extends AbstractControllerTest { Assert.assertEquals(savedDeviceProfile.getType(), foundDeviceProfileInfo.getType()); } + @Test + public void testFindDeviceProfileInfosByIds() throws Exception { + List deviceProfiles = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile " + i); + deviceProfiles.add(saveDeviceProfile(deviceProfile)); + } + + List expected = deviceProfiles.subList(5, 15); + + String idsParam = expected.stream() + .map(dp -> dp.getId().getId().toString()) + .collect(Collectors.joining(",")); + + DeviceProfileInfo[] result = doGet( + "/api/deviceProfileInfos?deviceProfileIds=" + idsParam, + DeviceProfileInfo[].class + ); + + Assert.assertNotNull(result); + Assert.assertEquals(expected.size(), result.length); + + Map infoById = Arrays.stream(result) + .collect(Collectors.toMap(info -> info.getId().getId(), Function.identity())); + + for (DeviceProfile dp : expected) { + UUID id = dp.getId().getId(); + DeviceProfileInfo info = infoById.get(id); + Assert.assertNotNull("DeviceProfileInfo not found for id " + id, info); + + Assert.assertEquals(dp.getId(), info.getId()); + Assert.assertEquals(dp.getName(), info.getName()); + Assert.assertEquals(dp.getType(), info.getType()); + } + } + @Test public void whenGetDeviceProfileInfoById_thenPermissionsAreChecked() throws Exception { DeviceProfile deviceProfile = createDeviceProfile("Device profile 1", null); diff --git a/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java index a6a022347f..72a6697927 100644 --- a/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java @@ -52,7 +52,12 @@ import org.thingsboard.server.dao.rule.RuleChainDao; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.containsString; @@ -231,6 +236,44 @@ public class RuleChainControllerTest extends AbstractControllerTest { Assert.assertEquals(savedRuleChain, foundRuleChain); } + @Test + public void testFindRuleChainsByIds() throws Exception { + List ruleChains = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + RuleChain ruleChain = new RuleChain(); + ruleChain.setName("RuleChain " + i); + ruleChains.add(doPost("/api/ruleChain", ruleChain, RuleChain.class)); + } + + List expected = ruleChains.subList(5, 15); + + String idsParam = expected.stream() + .map(rc -> rc.getId().getId().toString()) + .collect(Collectors.joining(",")); + + RuleChain[] result = doGet( + "/api/ruleChains?ruleChainIds=" + idsParam, + RuleChain[].class + ); + + Assert.assertNotNull(result); + Assert.assertEquals(expected.size(), result.length); + + Map rcById = Arrays.stream(result) + .collect(Collectors.toMap(rc -> rc.getId().getId(), Function.identity())); + + for (RuleChain rc : expected) { + UUID id = rc.getId().getId(); + RuleChain found = rcById.get(id); + Assert.assertNotNull("RuleChain not found for id " + id, found); + + Assert.assertEquals(rc.getId(), found.getId()); + Assert.assertEquals(rc.getName(), found.getName()); + Assert.assertEquals(rc.getTenantId(), found.getTenantId()); + } + } + + @Test public void testDeleteRuleChain() throws Exception { RuleChain ruleChain = new RuleChain(); diff --git a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java index ba45be8e28..cfab873ea1 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java @@ -68,6 +68,7 @@ import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.QueueKey; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -77,6 +78,7 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -187,6 +189,42 @@ public class TenantControllerTest extends AbstractControllerTest { deleteTenant(savedTenant.getId()); } + @Test + public void testFindTenantsByIds() throws Exception { + loginSysAdmin(); + + List savedTenants = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant " + i); + savedTenants.add(saveTenant(tenant)); + } + + String idsParam = savedTenants.stream() + .map(t -> t.getId().getId().toString()) + .collect(Collectors.joining(",")); + + Tenant[] foundTenants = doGet("/api/tenants?tenantIds=" + idsParam, Tenant[].class); + + Assert.assertNotNull(foundTenants); + Assert.assertEquals(savedTenants.size(), foundTenants.length); + + Map foundById = Arrays.stream(foundTenants) + .collect(Collectors.toMap(t -> t.getId().getId(), Function.identity())); + + for (Tenant savedTenant : savedTenants) { + UUID id = savedTenant.getId().getId(); + Tenant foundTenant = foundById.get(id); + Assert.assertNotNull("Tenant not found for id " + id, foundTenant); + Assert.assertEquals(savedTenant, foundTenant); + } + + for (Tenant savedTenant : savedTenants) { + deleteTenant(savedTenant.getId()); + } + } + + @Test public void testFindTenantInfoById() throws Exception { loginSysAdmin(); diff --git a/application/src/test/java/org/thingsboard/server/controller/TenantProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/TenantProfileControllerTest.java index 8f83f2c186..4862a00125 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TenantProfileControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TenantProfileControllerTest.java @@ -42,8 +42,12 @@ import org.thingsboard.server.queue.TbQueueCallback; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; import java.util.stream.Collectors; import static org.hamcrest.Matchers.containsString; @@ -120,6 +124,43 @@ public class TenantProfileControllerTest extends AbstractControllerTest { Assert.assertEquals(savedTenantProfile.getName(), foundTenantProfileInfo.getName()); } + @Test + public void testFindTenantProfilesByIds() throws Exception { + loginSysAdmin(); + List tenantProfiles = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile " + i); + tenantProfiles.add(doPost("/api/tenantProfile", tenantProfile, TenantProfile.class)); + } + + List expected = tenantProfiles.subList(2, 7); + + String idsParam = expected.stream() + .map(tp -> tp.getId().getId().toString()) + .collect(Collectors.joining(",")); + + TenantProfile[] result = doGet( + "/api/tenantProfiles?ids=" + idsParam, + TenantProfile[].class + ); + + Assert.assertNotNull(result); + Assert.assertEquals(expected.size(), result.length); + + Map tpById = Arrays.stream(result) + .collect(Collectors.toMap(tp -> tp.getId().getId(), Function.identity())); + + for (TenantProfile tp : expected) { + UUID id = tp.getId().getId(); + TenantProfile found = tpById.get(id); + Assert.assertNotNull("TenantProfile not found for id " + id, found); + + Assert.assertEquals(tp.getId(), found.getId()); + Assert.assertEquals(tp.getName(), found.getName()); + } + } + + @Test public void testFindDefaultTenantProfileInfo() throws Exception { loginSysAdmin(); diff --git a/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java index 28d43699fd..4379b57b45 100644 --- a/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java @@ -55,8 +55,12 @@ import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.user.UserDao; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -263,6 +267,37 @@ public class UserControllerTest extends AbstractControllerTest { Assert.assertEquals(savedUser, foundUser); } + @Test + public void testFindUsersByIds() throws Exception { + loginSysAdmin(); + List savedUsers = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + User user = createTenantAdminUser(); + savedUsers.add(doPost("/api/user", user, User.class)); + } + + String idsParam = savedUsers.stream() + .map(u -> u.getId().getId().toString()) + .collect(Collectors.joining(",")); + + User[] foundUsers = doGet("/api/users?userIds=" + idsParam, User[].class); + + Assert.assertNotNull(foundUsers); + Assert.assertEquals(savedUsers.size(), foundUsers.length); + + Map foundById = Arrays.stream(foundUsers) + .collect(Collectors.toMap(u -> u.getId().getId(), Function.identity())); + + for (User savedUser : savedUsers) { + User foundUser = foundById.get(savedUser.getId().getId()); + Assert.assertNotNull("User not found for id " + savedUser.getId().getId(), foundUser); + + foundUser.setAdditionalInfo(savedUser.getAdditionalInfo()); + Assert.assertEquals(savedUser, foundUser); + } + } + + @Test public void testSaveUserWithSameEmail() throws Exception { loginSysAdmin(); diff --git a/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java index 3440f26ea8..0b1c2d282e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java @@ -33,8 +33,13 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -150,6 +155,37 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { Assert.assertEquals(savedWidgetsBundle, foundWidgetsBundle); } + @Test + public void testFindWidgetsBundlesByIds() throws Exception { + List savedWidgetsBundles = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + WidgetsBundle widgetsBundle = new WidgetsBundle(); + widgetsBundle.setTitle("My widgets bundle " + i); + savedWidgetsBundles.add(doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class)); + } + + String idsParam = savedWidgetsBundles.stream() + .map(wb -> wb.getId().getId().toString()) + .collect(Collectors.joining(",")); + + WidgetsBundle[] foundWidgetsBundles = + doGet("/api/widgetsBundles?widgetsBundleIds=" + idsParam, WidgetsBundle[].class); + + Assert.assertNotNull(foundWidgetsBundles); + Assert.assertEquals(savedWidgetsBundles.size(), foundWidgetsBundles.length); + + Map foundById = Arrays.stream(foundWidgetsBundles) + .collect(Collectors.toMap(wb -> wb.getId().getId(), Function.identity())); + + for (WidgetsBundle savedWidgetsBundle : savedWidgetsBundles) { + UUID id = savedWidgetsBundle.getId().getId(); + WidgetsBundle foundWidgetsBundle = foundById.get(id); + Assert.assertNotNull("WidgetsBundle not found for id " + id, foundWidgetsBundle); + Assert.assertEquals(savedWidgetsBundle, foundWidgetsBundle); + } + } + + @Test public void testDeleteWidgetsBundle() throws Exception { WidgetsBundle widgetsBundle = new WidgetsBundle(); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java index bf29654941..e867656d4c 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.asset; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.asset.AssetProfileInfo; @@ -62,4 +63,6 @@ public interface AssetProfileService extends EntityDaoService { List findAssetProfileNamesByTenantId(TenantId tenantId, boolean activeOnly); + ListenableFuture> findAssetProfilesByIdsAsync(TenantId tenantId, List assetProfileIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java index d478e2099a..82a5605409 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.EntityDaoService; +import java.util.List; import java.util.Optional; public interface CustomerService extends EntityDaoService { @@ -47,4 +48,6 @@ public interface CustomerService extends EntityDaoService { void deleteCustomersByTenantId(TenantId tenantId); + ListenableFuture> findCustomersByTenantIdAndIdsAsync(TenantId tenantId, List customerIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java index 264a808c97..18efebc92d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java @@ -80,4 +80,6 @@ public interface DashboardService extends EntityDaoService { PageData findAllDashboardsIds(PageLink pageLink); + ListenableFuture> findDashboardInfoByIdsAsync(TenantId tenantId, List dashboardIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java index 5a2b95bc1b..3bbd760eec 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.device; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileInfo; import org.thingsboard.server.common.data.EntityInfo; @@ -64,4 +65,6 @@ public interface DeviceProfileService extends EntityDaoService { List findDeviceProfileNamesByTenantId(TenantId tenantId, boolean activeOnly); + ListenableFuture> findDeviceProfilesByIdsAsync(TenantId tenantId, List deviceProfileIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java index a2356ee149..fd84cc4c82 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java @@ -117,4 +117,6 @@ public interface RuleChainService extends EntityDaoService { void deleteRuleNodes(TenantId tenantId, RuleChainId ruleChainId); + ListenableFuture> findRuleChainsByIdsAsync(TenantId tenantId, List ruleChainIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java index d70bcef209..db9b77e161 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java @@ -55,4 +55,6 @@ public interface TenantService extends EntityDaoService { PageData findTenantsIds(PageLink pageLink); + ListenableFuture> findTenantsByIdsAsync(TenantId callerId, List tenantIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java index 160e02fbc8..629f1c1db5 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java @@ -110,4 +110,7 @@ public interface UserService extends EntityDaoService { void removeMobileSession(TenantId tenantId, String mobileToken); int countTenantAdmins(TenantId tenantId); + + ListenableFuture> findUsersByTenantIdAndIdsAsync(TenantId tenantId, List userIds); + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java index 9cb699cca4..5341b8862b 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.widget; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.page.PageData; @@ -52,4 +53,8 @@ public interface WidgetsBundleService extends EntityDaoService { void updateSystemWidgets(Stream bundles, Stream widgets); + ListenableFuture> findSystemWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds); + + ListenableFuture> findAllTenantWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds); + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java index 290213b97d..f98a344460 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java @@ -31,7 +31,7 @@ import java.util.UUID; @Value @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true, exclude = "image") -public class DeviceProfileInfo extends EntityInfo { +public class DeviceProfileInfo extends EntityInfo implements HasTenantId { @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ") private final String image; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java index a530759d03..ae06f33825 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java @@ -23,6 +23,7 @@ import lombok.ToString; import lombok.Value; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; @@ -33,7 +34,7 @@ import java.util.UUID; @Value @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true, exclude = "image") -public class AssetProfileInfo extends EntityInfo { +public class AssetProfileInfo extends EntityInfo implements HasTenantId { @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of asset profiles in the grid view. ") private final String image; diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java index da6acf6ca3..d56e794b93 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.asset; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.asset.AssetProfileInfo; @@ -51,4 +52,6 @@ public interface AssetProfileDao extends Dao, ExportableEntityDao< List findTenantAssetProfileNames(UUID tenantId, boolean activeOnly); + ListenableFuture> findAssetProfilesByTenantIdAndIdsAsync(UUID tenantId, List assetProfileIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index 4ddbabb5b6..63a5e1b241 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.asset; import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.hibernate.exception.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; @@ -51,7 +52,9 @@ import java.util.Optional; import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("AssetProfileDaoService") @Slf4j @@ -345,6 +348,14 @@ public class AssetProfileServiceImpl extends CachedVersionedEntityService> findAssetProfilesByIdsAsync(TenantId tenantId, List assetProfileIds) { + log.trace("Executing findAssetProfilesByIdsAsync, tenantId [{}], assetProfileIds [{}]", tenantId, assetProfileIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(assetProfileIds, ids -> "Incorrect assetProfileIds " + ids); + return assetProfileDao.findAssetProfilesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(assetProfileIds)); + } + private final PaginatedRemover tenantAssetProfilesRemover = new PaginatedRemover<>() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java index c6bfa970a0..9b3a22eaaa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.customer; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -24,6 +25,7 @@ import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.ExportableEntityDao; import org.thingsboard.server.dao.TenantEntityDao; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -78,4 +80,6 @@ public interface CustomerDao extends Dao, TenantEntityDao, E */ PageData findCustomersWithTheSameTitle(PageLink pageLink); + ListenableFuture> findCustomersByTenantIdAndIdsAsync(UUID tenantId, List customerIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java index 9aee422030..10299e3223 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java @@ -55,9 +55,11 @@ import org.thingsboard.server.dao.user.UserService; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("CustomerDaoService") @Slf4j @@ -263,6 +265,14 @@ public class CustomerServiceImpl extends AbstractCachedEntityService> findCustomersByTenantIdAndIdsAsync(TenantId tenantId, List customerIds) { + log.trace("Executing findCustomersByTenantIdAndIdsAsync, tenantId [{}], customerIds [{}]", tenantId, customerIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(customerIds, ids -> "Incorrect customerIds " + ids); + return customerDao.findCustomersByTenantIdAndIdsAsync(tenantId.getId(), customerIds.stream().map(CustomerId::getId).collect(Collectors.toList())); + } + @Override public void deleteByTenantId(TenantId tenantId) { deleteCustomersByTenantId(tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java index 6a3ec3295e..3687c01d02 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.dashboard; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -22,6 +23,7 @@ import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.ImageContainerDao; import org.thingsboard.server.dao.ResourceContainerDao; +import java.util.List; import java.util.UUID; /** @@ -81,4 +83,6 @@ public interface DashboardInfoDao extends Dao, ImageContainerDao< String findTitleById(UUID tenantId, UUID dashboardId); + ListenableFuture> findDashboardsByIdsAsync(UUID tenantId, List dashboardIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java index 9d8abe467c..7838c1a717 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java @@ -63,7 +63,9 @@ import java.util.Map; import java.util.Optional; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("DashboardDaoService") @Slf4j @@ -409,6 +411,13 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb return dashboardDao.findAllIds(pageLink); } + @Override + public ListenableFuture> findDashboardInfoByIdsAsync(TenantId tenantId, List dashboardIds) { + log.trace("Executing findDashboardInfoByIdsAsync, dashboardIds [{}]", dashboardIds); + validateIds(dashboardIds, ids -> "Incorrect dashboardIds " + ids); + return dashboardInfoDao.findDashboardsByIdsAsync(tenantId.getId(), toUUIDs(dashboardIds)); + } + private final PaginatedRemover tenantDashboardsRemover = new PaginatedRemover<>() { @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java index f2c021ea8a..470881a690 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.device; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileInfo; import org.thingsboard.server.common.data.EntityInfo; @@ -53,4 +54,6 @@ public interface DeviceProfileDao extends Dao, ExportableEntityDa List findTenantDeviceProfileNames(UUID tenantId, boolean activeOnly); + ListenableFuture> findDeviceProfilesByTenantIdAndIdsAsync(UUID tenantId, List deviceProfileIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java index f782585888..eddf18e3c2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.device; import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.ListenableFuture; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -66,7 +67,9 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validateString; @Service("DeviceProfileDaoService") @@ -391,6 +394,14 @@ public class DeviceProfileServiceImpl extends CachedVersionedEntityService> findDeviceProfilesByIdsAsync(TenantId tenantId, List deviceProfileIds) { + log.trace("Executing findDeviceProfilesByIdsAsync, tenantId [{}], deviceProfileIds [{}]", tenantId, deviceProfileIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(deviceProfileIds, ids -> "Incorrect deviceProfileIds " + ids); + return deviceProfileDao.findDeviceProfilesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(deviceProfileIds)); + } + private final PaginatedRemover tenantDeviceProfilesRemover = new PaginatedRemover<>() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index 8912e47c5b..c1561084b9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -85,6 +85,7 @@ import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.common.data.DataConstants.TENANT; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validatePageLink; @@ -869,6 +870,14 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC } } + @Override + public ListenableFuture> findRuleChainsByIdsAsync(TenantId tenantId, List ruleChainIds) { + log.trace("Executing findRuleChainsByIdsAsync, tenantId [{}], ruleChainIds [{}]", tenantId, ruleChainIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(ruleChainIds, ids -> "Incorrect ruleChainIds " + ids); + return ruleChainDao.findRuleChainsByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(ruleChainIds)); + } + @Override public Optional> findEntity(TenantId tenantId, EntityId entityId) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java index ac716bb4fc..7b4e9a7fb9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.rule; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; @@ -28,6 +29,7 @@ import org.thingsboard.server.dao.ResourceContainerDao; import org.thingsboard.server.dao.TenantEntityDao; import java.util.Collection; +import java.util.List; import java.util.UUID; /** @@ -83,4 +85,6 @@ public interface RuleChainDao extends Dao, TenantEntityDao Collection findByTenantIdAndTypeAndName(TenantId tenantId, RuleChainType type, String name); + ListenableFuture> findRuleChainsByTenantIdAndIdsAsync(UUID tenantId, List ruleChainIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetProfileRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetProfileRepository.java index eb35a4e18e..a9e707ebf2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetProfileRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetProfileRepository.java @@ -87,4 +87,10 @@ public interface AssetProfileRepository extends JpaRepository :id ORDER BY a.id") List findNextBatch(@Param("id") UUID id, Limit limit); + @Query("SELECT new org.thingsboard.server.common.data.asset.AssetProfileInfo(a.id, a.tenantId, a.name, a.image, a.defaultDashboardId) " + + "FROM AssetProfileEntity a WHERE " + + "a.tenantId = :tenantId AND a.id IN :assetProfileIds") + List findAssetProfileInfosByTenantIdAndIdIn(@Param("tenantId") UUID tenantId, + @Param("assetProfileIds") List assetProfileIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java index eeab5a338a..99093827e5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.asset; +import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.domain.PageRequest; @@ -105,6 +106,11 @@ public class JpaAssetProfileDao extends JpaAbstractDao> findAssetProfilesByTenantIdAndIdsAsync(UUID tenantId, List assetProfileIds) { + return service.submit(() -> assetProfileRepository.findAssetProfileInfosByTenantIdAndIdIn(tenantId, assetProfileIds)); + } + @Override public AssetProfile findByTenantIdAndExternalId(UUID tenantId, UUID externalId) { return DaoUtil.getData(assetProfileRepository.findByTenantIdAndExternalId(tenantId, externalId)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java index 8ad7311423..d53296b9ab 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java @@ -62,4 +62,6 @@ public interface CustomerRepository extends JpaRepository, "c.title, c.version, c.additionalInfo, c.country, c.state, c.city, c.address, c.address2, c.zip, c.phone, c.email) " + "FROM CustomerEntity c WHERE c.id > :id ORDER BY c.id") List findNextBatch(@Param("id") UUID id, Limit limit); + + List findCustomersByTenantIdAndIdIn(UUID tenantId, List customerIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java index 75e7179391..d1a31faaaf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.customer; +import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -107,6 +108,11 @@ public class JpaCustomerDao extends JpaAbstractDao imp ); } + @Override + public ListenableFuture> findCustomersByTenantIdAndIdsAsync(UUID tenantId, List customerIds) { + return service.submit(() -> DaoUtil.convertDataList(customerRepository.findCustomersByTenantIdAndIdIn(tenantId, customerIds))); + } + @Override public PageData findAllByTenantId(TenantId tenantId, PageLink pageLink) { return findByTenantId(tenantId.getId(), pageLink); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java index 32ac596562..2198869c24 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java @@ -20,6 +20,7 @@ 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.DashboardInfo; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.dao.model.sql.DashboardInfoEntity; @@ -99,4 +100,6 @@ public interface DashboardInfoRepository extends JpaRepository findDashboardInfosByResourceLink(@Param("link") String link, Pageable pageable); + List findByIdIn(List dashboardIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java index 0e04c94a46..f3999a10c6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.dashboard; +import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; @@ -126,6 +127,11 @@ public class JpaDashboardInfoDao extends JpaAbstractDao> findDashboardsByIdsAsync(UUID tenantId, List dashboardIds) { + return service.submit(() -> DaoUtil.convertDataList(dashboardInfoRepository.findByIdIn(dashboardIds))); + } + @Override public List findByTenantAndImageLink(TenantId tenantId, String imageLink, int limit) { return DaoUtil.convertDataList(dashboardInfoRepository.findByTenantAndImageLink(tenantId.getId(), imageLink, limit)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java index 88d4780f9d..4e8a536dd1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java @@ -59,6 +59,11 @@ public interface DeviceProfileRepository extends JpaRepository findDeviceProfileInfosByTenantIdAndIdIn(@Param("tenantId") UUID tenantId, @Param("deviceProfileIds") List deviceProfileIds); + @Query("SELECT d FROM DeviceProfileEntity d " + "WHERE d.tenantId = :tenantId AND d.isDefault = true") DeviceProfileEntity findByDefaultTrueAndTenantId(@Param("tenantId") UUID tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java index ebd8c78ed0..41dbf3978e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.device; +import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.domain.PageRequest; @@ -123,6 +124,11 @@ public class JpaDeviceProfileDao extends JpaAbstractDao> findDeviceProfilesByTenantIdAndIdsAsync(UUID tenantId, List deviceProfileIds) { + return service.submit(() -> deviceProfileRepository.findDeviceProfileInfosByTenantIdAndIdIn(tenantId, deviceProfileIds)); + } + @Override public DeviceProfile findByTenantIdAndExternalId(UUID tenantId, UUID externalId) { return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndExternalId(tenantId, externalId)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java index 4a6427a7e5..f541627309 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.rule; +import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; @@ -112,6 +113,11 @@ public class JpaRuleChainDao extends JpaAbstractDao return DaoUtil.convertDataList(ruleChainRepository.findByTenantIdAndTypeAndName(tenantId.getId(), type, name)); } + @Override + public ListenableFuture> findRuleChainsByTenantIdAndIdsAsync(UUID tenantId, List ruleChainIds) { + return service.submit(() -> DaoUtil.convertDataList(ruleChainRepository.findRuleChainsByTenantIdAndIdIn(tenantId, ruleChainIds))); + } + @Override public Long countByTenantId(TenantId tenantId) { return ruleChainRepository.countByTenantId(tenantId.getId()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java index 4bf648cbbd..2dbb61f07c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java @@ -90,4 +90,7 @@ public interface RuleChainRepository extends JpaRepository :id ORDER BY r.id") List findNextBatch(@Param("id") UUID id, Limit limit); + + List findRuleChainsByTenantIdAndIdIn(UUID tenantId, List ruleChainIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java index fb558dab0c..781753bb7d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.tenant; +import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -98,6 +99,11 @@ public class JpaTenantDao extends JpaAbstractDao implement return DaoUtil.getData(tenantRepository.findFirstByTitle(name)); } + @Override + public ListenableFuture> findTenantsByIdsAsync(UUID tenantId, List tenantIds) { + return service.submit(() -> DaoUtil.convertDataList(tenantRepository.findTenantsByIdIn(tenantIds))); + } + @Override public List findNextBatch(UUID id, int batchSize) { return tenantRepository.findNextBatch(id, Limit.of(batchSize)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java index 08859d5f63..db10d971a2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantRepository.java @@ -62,4 +62,6 @@ public interface TenantRepository extends JpaRepository { TenantEntity findFirstByTitle(String name); + List findTenantsByIdIn(List tenantIds); + } 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 753955089c..3b3f4dc15c 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 @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.user; +import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -141,6 +142,11 @@ public class JpaUserDao extends JpaAbstractDao implements User return userRepository.countByTenantIdAndAuthority(tenantId, Authority.TENANT_ADMIN); } + @Override + public ListenableFuture> findUsersByTenantIdAndIdsAsync(UUID tenantId, List userIds) { + return service.submit(() -> DaoUtil.convertDataList(userRepository.findUsersByTenantIdAndIdIn(tenantId, userIds))); + } + @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 2254377af3..5dacf2ad09 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 @@ -80,4 +80,7 @@ public interface UserRepository extends JpaRepository { List findNextBatch(@Param("id") UUID id, Limit limit); int countByTenantIdAndAuthority(UUID tenantId, Authority authority); + + List findUsersByTenantIdAndIdIn(UUID tenantId, List userIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java index bc81be054a..b1481d636a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.sql.widget; +import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -111,6 +112,17 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao> findSystemWidgetBundlesByIdsAsync(UUID tenantId, List widgetsBundleIds) { + return service.submit(() -> DaoUtil.convertDataList(widgetsBundleRepository.findSystemWidgetsBundlesByIdIn(NULL_UUID, widgetsBundleIds))); + } + + @Override + public ListenableFuture> findAllTenantWidgetBundlesByTenantIdAndIdsAsync(UUID tenantId, List widgetsBundleIds) { + return service.submit(() -> DaoUtil.convertDataList(widgetsBundleRepository + .findAllTenantWidgetsBundlesByTenantIdAndIdIn(tenantId, NULL_UUID, widgetsBundleIds))); + } + private PageData findTenantWidgetsBundlesByTenantIds(List tenantIds, WidgetsBundleFilter widgetsBundleFilter, PageLink pageLink) { if (widgetsBundleFilter.isFullSearch()) { return DaoUtil.toPageData( diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java index de778588dd..53053eb3c0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java @@ -146,4 +146,16 @@ public interface WidgetsBundleRepository extends JpaRepository :id ORDER BY w.id") List findNextBatch(@Param("id") UUID id, Limit limit); + + @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :systemTenantId " + + "AND wb.id IN :widgetsBundleIds") + List findSystemWidgetsBundlesByIdIn(@Param("systemTenantId") UUID systemTenantId, + @Param("widgetsBundleIds") List widgetsBundleIds); + + @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId IN (:tenantId, :nullTenantId) " + + "AND wb.id IN :widgetsBundleIds") + List findAllTenantWidgetsBundlesByTenantIdAndIdIn(@Param("tenantId") UUID tenantId, + @Param("nullTenantId") UUID nullTenantId, + @Param("widgetsBundleIds") List widgetsBundleIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java index 8ff3999c4e..5bab7e6295 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.tenant; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantInfo; import org.thingsboard.server.common.data.id.TenantId; @@ -42,4 +43,6 @@ public interface TenantDao extends Dao { Tenant findTenantByName(TenantId tenantId, String name); + ListenableFuture> findTenantsByIdsAsync(UUID tenantId, List tenantIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index bd5a621562..a6f8bac498 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -53,7 +53,9 @@ import java.util.Optional; import java.util.function.Consumer; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("TenantDaoService") @Slf4j @@ -224,6 +226,13 @@ public class TenantServiceImpl extends AbstractCachedEntityService> findTenantsByIdsAsync(TenantId callerId, List tenantIds) { + log.trace("Executing findTenantsByIdsAsync, callerId [{}], tenantIds [{}]", callerId, tenantIds); + validateIds(tenantIds, ids -> "Incorrect tenantIds " + ids); + return tenantDao.findTenantsByIdsAsync(callerId.getId(), toUUIDs(tenantIds)); + } + @Override public boolean tenantExists(TenantId tenantId) { return existsTenantCache.getAndPutInTransaction(tenantId, () -> tenantDao.existsById(tenantId, tenantId.getId()), false); 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 127aa6141a..26e98a4edf 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 @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.user; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -102,4 +103,7 @@ public interface UserDao extends Dao, TenantEntityDao { PageData findByAuthorityAndTenantProfilesIds(Authority authority, List tenantProfilesIds, PageLink pageLink); int countTenantAdmins(UUID tenantId); + + ListenableFuture> findUsersByTenantIdAndIdsAsync(UUID tenantId, List userIds); + } 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 595a2a6611..dbf3c72c5b 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 @@ -75,7 +75,9 @@ import java.util.concurrent.TimeUnit; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.common.data.StringUtils.generateSafeToken; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validatePageLink; import static org.thingsboard.server.dao.service.Validator.validateString; @@ -492,6 +494,14 @@ public class UserServiceImpl extends AbstractCachedEntityService> findUsersByTenantIdAndIdsAsync(TenantId tenantId, List userIds) { + log.trace("Executing findUsersByTenantIdAndIdsAsync, tenantId [{}], userIds [{}]", tenantId, userIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(userIds, ids -> "Incorrect userIds " + ids); + return userDao.findUsersByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(userIds)); + } + private Optional findMobileSessionInfo(TenantId tenantId, UserId userId) { return Optional.ofNullable(userSettingsService.findUserSettings(tenantId, userId, UserSettingsType.MOBILE)) .map(UserSettings::getSettings).map(settings -> JacksonUtil.treeToValue(settings, UserMobileSessionInfo.class)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java index 18a63944e8..b9e03072b1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.widget; +import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.page.PageData; @@ -25,6 +26,7 @@ import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.ExportableEntityDao; import org.thingsboard.server.dao.ImageContainerDao; +import java.util.List; import java.util.UUID; /** @@ -87,5 +89,9 @@ public interface WidgetsBundleDao extends Dao, ExportableEntityDa PageData findAllWidgetsBundles(PageLink pageLink); + ListenableFuture> findSystemWidgetBundlesByIdsAsync(UUID tenantId, List widgetsBundleIds); + + ListenableFuture> findAllTenantWidgetBundlesByTenantIdAndIdsAsync(UUID tenantId, List widgetsBundleIds); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java index 5b5930fb0a..5d4b6d4bb0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.widget; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; @@ -48,7 +49,10 @@ import java.util.Optional; import java.util.stream.Stream; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.entity.AbstractEntityService.checkConstraintViolation; +import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("WidgetsBundleDaoService") @Slf4j @@ -252,6 +256,22 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService { }); } + @Override + public ListenableFuture> findSystemWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds) { + log.trace("Executing findSystemWidgetsBundlesByIdsAsync, tenantId [{}], widgetsBundleIds [{}]", tenantId, widgetsBundleIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(widgetsBundleIds, ids -> "Incorrect widgetsBundleIds " + ids); + return widgetsBundleDao.findSystemWidgetBundlesByIdsAsync(tenantId.getId(), toUUIDs(widgetsBundleIds)); + } + + @Override + public ListenableFuture> findAllTenantWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds) { + log.trace("Executing findAllTenantWidgetsBundlesByIdsAsync, tenantId [{}], widgetsBundleIds [{}]", tenantId, widgetsBundleIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(widgetsBundleIds, ids -> "Incorrect widgetsBundleIds " + ids); + return widgetsBundleDao.findAllTenantWidgetBundlesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(widgetsBundleIds)); + } + private WidgetTypeDetails updateSystemWidget(JsonNode widgetTypeJson) { WidgetTypeDetails widgetTypeDetails = JacksonUtil.treeToValue(widgetTypeJson, WidgetTypeDetails.class); WidgetType existingWidget = widgetTypeService.findWidgetTypeByTenantIdAndFqn(TenantId.SYS_TENANT_ID, widgetTypeDetails.getFqn()); From 0af925433a91525d25cc2f64c13f24c477db4d39 Mon Sep 17 00:00:00 2001 From: Artem Barysh Date: Mon, 17 Nov 2025 18:35:23 +0200 Subject: [PATCH 2/7] minor improvements --- .../controller/AssetProfileController.java | 17 +++++------------ .../controller/DeviceProfileController.java | 16 +++++----------- .../permission/AccessControlService.java | 2 ++ .../permission/DefaultAccessControlService.java | 10 ++++++++++ .../security/permission/PermissionChecker.java | 1 - .../server/common/data/DeviceProfileInfo.java | 2 +- .../common/data/asset/AssetProfileInfo.java | 3 +-- 7 files changed, 24 insertions(+), 27 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index 9415e7194e..72223f129a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -48,8 +48,8 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.concurrent.ExecutionException; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID; @@ -236,7 +236,9 @@ public class AssetProfileController extends BaseController { @Parameter(description = "A list of asset profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("assetProfileIds") String[] strAssetProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("assetProfileIds", strAssetProfileIds); - + if (!accessControlService.hasPermission(getCurrentUser(), Resource.ASSET_PROFILE, Operation.READ)) { + return Collections.emptyList(); + } SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); List assetProfileIds = new ArrayList<>(); @@ -244,16 +246,7 @@ public class AssetProfileController extends BaseController { assetProfileIds.add(new AssetProfileId(toUUID(strAssetProfileId))); } - return Objects.requireNonNull(checkNotNull(assetProfileService.findAssetProfilesByIdsAsync(tenantId, assetProfileIds).get())) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(user, Resource.ASSET_PROFILE, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); + return checkNotNull(assetProfileService.findAssetProfilesByIdsAsync(tenantId, assetProfileIds).get()); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index 7f6f6bfa61..fd0cafb3ec 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -51,8 +51,8 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -292,6 +292,9 @@ public class DeviceProfileController extends BaseController { @Parameter(description = "A list of device profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("deviceProfileIds") String[] strDeviceProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("deviceProfileIds", strDeviceProfileIds); + if (!accessControlService.hasPermission(getCurrentUser(), Resource.DEVICE_PROFILE, Operation.READ)) { + return Collections.emptyList(); + } SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); List deviceProfileIds = new ArrayList<>(); @@ -299,16 +302,7 @@ public class DeviceProfileController extends BaseController { deviceProfileIds.add(new DeviceProfileId(toUUID(strDeviceProfileId))); } - return Objects.requireNonNull(checkNotNull(deviceProfileService.findDeviceProfilesByIdsAsync(tenantId, deviceProfileIds).get())) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(user, Resource.DEVICE_PROFILE, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); + return checkNotNull(deviceProfileService.findDeviceProfilesByIdsAsync(tenantId, deviceProfileIds).get()); } } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java index b760a54ade..1d8d0992ac 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/AccessControlService.java @@ -24,6 +24,8 @@ public interface AccessControlService { void checkPermission(SecurityUser user, Resource resource, Operation operation) throws ThingsboardException; + boolean hasPermission(SecurityUser user, Resource resource, Operation operation) throws ThingsboardException; + void checkPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException; boolean hasPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException; diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java index 9bf05e2d73..f8898f9660 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java @@ -55,6 +55,16 @@ public class DefaultAccessControlService implements AccessControlService { } } + @Override + @SuppressWarnings("unchecked") + public boolean hasPermission(SecurityUser user, Resource resource, Operation operation) throws ThingsboardException { + PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); + if (permissionChecker != null) { + return permissionChecker.hasPermission(user, operation); + } + return false; + } + @Override @SuppressWarnings("unchecked") public void checkPermission(SecurityUser user, Resource resource, diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java b/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java index 216d74fe2f..2fcf6b71fc 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/PermissionChecker.java @@ -16,7 +16,6 @@ package org.thingsboard.server.service.security.permission; import org.thingsboard.server.common.data.HasTenantId; -import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java index f98a344460..290213b97d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java @@ -31,7 +31,7 @@ import java.util.UUID; @Value @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true, exclude = "image") -public class DeviceProfileInfo extends EntityInfo implements HasTenantId { +public class DeviceProfileInfo extends EntityInfo { @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ") private final String image; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java index ae06f33825..a530759d03 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java @@ -23,7 +23,6 @@ import lombok.ToString; import lombok.Value; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; @@ -34,7 +33,7 @@ import java.util.UUID; @Value @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true, exclude = "image") -public class AssetProfileInfo extends EntityInfo implements HasTenantId { +public class AssetProfileInfo extends EntityInfo { @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of asset profiles in the grid view. ") private final String image; From b56e017ff1a5c7f15876adcb61f92df5abb32175 Mon Sep 17 00:00:00 2001 From: Artem Barysh Date: Mon, 17 Nov 2025 18:57:39 +0200 Subject: [PATCH 3/7] minor improvements --- .../server/controller/AssetProfileController.java | 4 ++-- .../server/controller/DeviceProfileController.java | 4 ++-- .../service/security/permission/TenantAdminPermissions.java | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index 72223f129a..8f0b7480ab 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -236,10 +236,10 @@ public class AssetProfileController extends BaseController { @Parameter(description = "A list of asset profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("assetProfileIds") String[] strAssetProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("assetProfileIds", strAssetProfileIds); - if (!accessControlService.hasPermission(getCurrentUser(), Resource.ASSET_PROFILE, Operation.READ)) { + SecurityUser user = getCurrentUser(); + if (!accessControlService.hasPermission(user, Resource.ASSET_PROFILE, Operation.READ)) { return Collections.emptyList(); } - SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); List assetProfileIds = new ArrayList<>(); for (String strAssetProfileId : strAssetProfileIds) { diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index fd0cafb3ec..7092a48c59 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -292,10 +292,10 @@ public class DeviceProfileController extends BaseController { @Parameter(description = "A list of device profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @RequestParam("deviceProfileIds") String[] strDeviceProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("deviceProfileIds", strDeviceProfileIds); - if (!accessControlService.hasPermission(getCurrentUser(), Resource.DEVICE_PROFILE, Operation.READ)) { + SecurityUser user = getCurrentUser(); + if (!accessControlService.hasPermission(user, Resource.DEVICE_PROFILE, Operation.READ)) { return Collections.emptyList(); } - SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); List deviceProfileIds = new ArrayList<>(); for (String strDeviceProfileId : strDeviceProfileIds) { 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 7a824ca735..9baf24e7d9 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 @@ -63,6 +63,11 @@ public class TenantAdminPermissions extends AbstractPermissions { public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker() { + @Override + public boolean hasPermission(SecurityUser user, Operation operation) { + return true; + } + @Override public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { if (!user.getTenantId().equals(entity.getTenantId())) { From 0dd37617e1fadb8b058ec8b17c4ce09aa900398a Mon Sep 17 00:00:00 2001 From: Artem Barysh Date: Wed, 26 Nov 2025 15:19:22 +0200 Subject: [PATCH 4/7] added get entity views by ids endpoint --- .../controller/EntityViewController.java | 49 +++++++++++++------ .../controller/EntityViewControllerTest.java | 33 +++++++++++++ .../dao/entityview/EntityViewService.java | 2 + .../server/dao/entityview/EntityViewDao.java | 2 + .../dao/entityview/EntityViewServiceImpl.java | 10 ++++ .../sql/entityview/EntityViewRepository.java | 2 + .../dao/sql/entityview/JpaEntityViewDao.java | 5 ++ 7 files changed, 87 insertions(+), 16 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index b1b6b6b1e3..c67f260422 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -17,11 +17,13 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.ListenableFuture; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -53,6 +55,7 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; @@ -347,14 +350,7 @@ public class EntityViewController extends BaseController { checkNotNull(query.getEntityViewTypes()); checkEntityId(query.getParameters().getEntityId(), Operation.READ); List entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(getTenantId(), query).get()); - entityViews = entityViews.stream().filter(entityView -> { - try { - accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView); - return true; - } catch (ThingsboardException e) { - return false; - } - }).collect(Collectors.toList()); + entityViews = filterEntityViewsByReadPermission(entityViews); return entityViews; } @@ -459,18 +455,39 @@ public class EntityViewController extends BaseController { } else { nonFilteredResult = entityViewService.findEntityViewsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); } - List filteredEntityViews = nonFilteredResult.getData().stream().filter(entityView -> { - try { - accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView); - return true; - } catch (ThingsboardException e) { - return false; - } - }).collect(Collectors.toList()); + List filteredEntityViews = filterEntityViewsByReadPermission(nonFilteredResult.getData()); PageData filteredResult = new PageData<>(filteredEntityViews, nonFilteredResult.getTotalPages(), nonFilteredResult.getTotalElements(), nonFilteredResult.hasNext()); return checkNotNull(filteredResult); } + + @ApiOperation(value = "Get Entity Views By Ids (getEntityViewsByIds)", + notes = "Requested entity views must be owned by tenant or assigned to customer which user is performing the request. ") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @GetMapping(value = "/entityViews", params = {"entityViewIds"}) + public List getEntityViewsByIds(@Parameter(description = "A list of entity view ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) + @RequestParam("entityViewIds") String[] strEntityViewIds) throws ThingsboardException, ExecutionException, InterruptedException { + checkArrayParameter("entityViewIds", strEntityViewIds); + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + List entityViewIds = new ArrayList<>(); + for (String strEntityViewId : strEntityViewIds) { + entityViewIds.add(new EntityViewId(toUUID(strEntityViewId))); + } + List entityViews = checkNotNull(entityViewService.findEntityViewsByTenantIdAndIdsAsync(tenantId, entityViewIds).get()); + return filterEntityViewsByReadPermission(entityViews); + } + + private List filterEntityViewsByReadPermission(List entityViews) { + return entityViews.stream().filter(entityView -> { + try { + return accessControlService.hasPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView); + } catch (ThingsboardException e) { + return false; + } + }).collect(Collectors.toList()); + } + } diff --git a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java index 10b49dfe1d..5b4c9d017b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java @@ -68,11 +68,14 @@ import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; import static java.util.concurrent.TimeUnit.HOURS; @@ -148,6 +151,36 @@ public class EntityViewControllerTest extends AbstractControllerTest { assertEquals(savedView, foundView); } + @Test + public void testFindEntityViewByIds() throws Exception { + List assetProfiles = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + assetProfiles.add(getNewSavedEntityView("Test entity view " + i)); + } + + List expected = assetProfiles.subList(5, 15); + + String idsParam = expected.stream() + .map(ap -> ap.getId().getId().toString()) + .collect(Collectors.joining(",")); + EntityView[] foundEntityViews = doGet("/api/entityViews?entityViewIds=" + idsParam, EntityView[].class); + + Assert.assertNotNull(foundEntityViews); + Assert.assertEquals(expected.size(), foundEntityViews.length); + + Map infoById = Arrays.stream(foundEntityViews) + .collect(Collectors.toMap(info -> info.getId().getId(), Function.identity())); + + for (EntityView entityView : expected) { + UUID id = entityView.getId().getId(); + EntityView view = infoById.get(id); + Assert.assertNotNull("Entity view not found for id " + id, view); + + Assert.assertEquals(entityView.getId(), view.getId()); + Assert.assertEquals(entityView.getName(), view.getName()); + } + } + @Test public void testSaveEntityView() throws Exception { String name = "Test entity view"; diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java index 5ec2dfc20e..e64cd0dd6d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java @@ -65,6 +65,8 @@ public interface EntityViewService extends EntityDaoService { PageData findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); + ListenableFuture> findEntityViewsByTenantIdAndIdsAsync(TenantId tenantId, List entityViewIds); + PageData findEntityViewInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); PageData findEntityViewsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, PageLink pageLink, String type); diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java index 17f84c7b06..52d077a3bb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java @@ -169,6 +169,8 @@ public interface EntityViewDao extends Dao, ExportableEntityDao> findEntityViewsByTenantIdAndIdsAsync(UUID tenantId, List entityViewIds); + /** * Find entity views by tenantId, edgeId, type and page link. * diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 3128036e0e..e135555659 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -62,7 +62,9 @@ import java.util.Optional; import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; +import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validatePageLink; import static org.thingsboard.server.dao.service.Validator.validateString; @@ -255,6 +257,14 @@ public class EntityViewServiceImpl extends CachedVersionedEntityService> findEntityViewsByTenantIdAndIdsAsync(TenantId tenantId, List entityViewIds) { + log.trace("Executing findEntityViewsByTenantIdAndIdsAsync, tenantId [{}], entityViewIds [{}]", tenantId, entityViewIds); + validateId(tenantId, id -> INCORRECT_TENANT_ID + id); + validateIds(entityViewIds, ids -> "Incorrect entityViewIds " + ids); + return entityViewDao.findEntityViewsByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(entityViewIds)); + } + @Override public PageData findEntityViewInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink) { log.trace("Executing findEntityViewInfosByTenantIdAndCustomerId, tenantId [{}], customerId [{}]," + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java index 6094e9b171..c61ec83335 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/EntityViewRepository.java @@ -122,6 +122,8 @@ public interface EntityViewRepository extends JpaRepository findEntityViewsByTenantIdAndIdIn(UUID tenantId, List entityViewIds); + @Query("SELECT DISTINCT ev.type FROM EntityViewEntity ev WHERE ev.tenantId = :tenantId") List findTenantEntityViewTypes(@Param("tenantId") UUID tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index 44d8a09ff4..fe3f63825f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -187,6 +187,11 @@ public class JpaEntityViewDao extends JpaAbstractDao> findEntityViewsByTenantIdAndIdsAsync(UUID tenantId, List entityViewIds) { + return service.submit(() -> DaoUtil.convertDataList(entityViewRepository.findEntityViewsByTenantIdAndIdIn(tenantId, entityViewIds))); + } + @Override public PageData findEntityViewsByTenantIdAndEdgeIdAndType(UUID tenantId, UUID edgeId, String type, PageLink pageLink) { log.debug("Try to find entity views by tenantId [{}], edgeId [{}], type [{}] and pageLink [{}]", tenantId, edgeId, type, pageLink); From 1641b6a4911d8109d3714f268e6522f2cb11df86 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 5 Dec 2025 10:38:08 +0200 Subject: [PATCH 5/7] removed redundant permission checks --- .../controller/AssetProfileController.java | 5 +---- .../server/controller/CustomerController.java | 13 ++--------- .../controller/RuleChainController.java | 12 +--------- .../server/controller/TenantController.java | 13 ++--------- .../server/controller/UserController.java | 22 ++++++++++--------- .../controller/WidgetsBundleController.java | 16 ++------------ .../DefaultAccessControlService.java | 14 ++++-------- 7 files changed, 24 insertions(+), 71 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index 8f0b7480ab..9c12880e96 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -237,16 +237,13 @@ public class AssetProfileController extends BaseController { @RequestParam("assetProfileIds") String[] strAssetProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("assetProfileIds", strAssetProfileIds); SecurityUser user = getCurrentUser(); - if (!accessControlService.hasPermission(user, Resource.ASSET_PROFILE, Operation.READ)) { - return Collections.emptyList(); - } TenantId tenantId = user.getTenantId(); List assetProfileIds = new ArrayList<>(); for (String strAssetProfileId : strAssetProfileIds) { assetProfileIds.add(new AssetProfileId(toUUID(strAssetProfileId))); } - return checkNotNull(assetProfileService.findAssetProfilesByIdsAsync(tenantId, assetProfileIds).get()); + return assetProfileService.findAssetProfilesByIdsAsync(tenantId, assetProfileIds).get(); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index e0f8cef1c8..ad547d3cc3 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -194,7 +194,7 @@ public class CustomerController extends BaseController { @ApiOperation(value = "Get customers by Customer Ids (getCustomersByIds)", notes = "Returns a list of Customer objects based on the provided ids." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @GetMapping(value = "/customers", params = {"customerIds"}) public List getCustomersByIds( @Parameter(description = "A list of customer ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) @@ -206,16 +206,7 @@ public class CustomerController extends BaseController { for (String strCustomerId : strCustomerIds) { customerIds.add(new CustomerId(toUUID(strCustomerId))); } - return Objects.requireNonNull(checkNotNull(customerService.findCustomersByTenantIdAndIdsAsync(tenantId, customerIds).get())) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(user, Resource.CUSTOMER, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); + return customerService.findCustomersByTenantIdAndIdsAsync(tenantId, customerIds).get(); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 4349ea22bf..c1aa3acc89 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -79,7 +79,6 @@ import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentMap; @@ -598,16 +597,7 @@ public class RuleChainController extends BaseController { for (String strRuleChainId : strRuleChainIds) { ruleChainIds.add(new RuleChainId(toUUID(strRuleChainId))); } - return Objects.requireNonNull(checkNotNull(ruleChainService.findRuleChainsByIdsAsync(tenantId, ruleChainIds).get())) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(user, Resource.RULE_CHAIN, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); + return ruleChainService.findRuleChainsByIdsAsync(tenantId, ruleChainIds).get(); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantController.java b/application/src/main/java/org/thingsboard/server/controller/TenantController.java index 22ceb33b8d..8187b3018e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantController.java @@ -174,7 +174,7 @@ public class TenantController extends BaseController { return checkNotNull(tenantService.findTenantInfos(pageLink)); } - @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") @GetMapping(value = "/tenants", params = {"tenantIds"}) public List getTenantsByIds( @Parameter(description = "A list of tenant ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string"))) @@ -186,16 +186,7 @@ public class TenantController extends BaseController { for (String strTenantId : strTenantIds) { tenantIds.add(new TenantId(toUUID(strTenantId))); } - return Objects.requireNonNull(checkNotNull(tenantService.findTenantsByIdsAsync(tenantId, tenantIds).get())) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(user, Resource.TENANT, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); + return tenantService.findTenantsByIdsAsync(tenantId, tenantIds).get(); } } 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 e0adf27a97..8da3978aeb 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -611,16 +611,18 @@ public class UserController extends BaseController { for (String strUserId : strUserIds) { userIds.add(new UserId(toUUID(strUserId))); } - return Objects.requireNonNull(checkNotNull(userService.findUsersByTenantIdAndIdsAsync(tenantId, userIds).get())) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(user, Resource.USER, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); + List users = checkNotNull(userService.findUsersByTenantIdAndIdsAsync(tenantId, userIds).get()); + return filterUsersByReadPermission(users); + } + + private List filterUsersByReadPermission(List users) { + return users.stream().filter(user -> { + try { + return accessControlService.hasPermission(getCurrentUser(), Resource.USER, Operation.READ, user.getId(), user); + } catch (ThingsboardException e) { + return false; + } + }).collect(Collectors.toList()); } private void checkNotReserved(String strType, UserSettingsType type) throws ThingsboardException { diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 1060c7fe94..021aaf9d13 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -253,23 +253,11 @@ public class WidgetsBundleController extends BaseController { for (String strWidgetsBundleId : strWidgetsBundleIds) { widgetsBundleIds.add(new WidgetsBundleId(toUUID(strWidgetsBundleId))); } - List result; if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { - result = checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get()); + return widgetsBundleService.findSystemWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get(); } else { - result = checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get()); + return widgetsBundleService.findAllTenantWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get(); } - - return Objects.requireNonNull(result) - .stream() - .filter(e -> { - try { - return accessControlService.hasPermission(getCurrentUser(), Resource.WIDGETS_BUNDLE, Operation.READ, e.getId(), e); - } catch (ThingsboardException ex) { - return false; - } - }) - .toList(); } } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java index f8898f9660..055025dd30 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/DefaultAccessControlService.java @@ -58,11 +58,8 @@ public class DefaultAccessControlService implements AccessControlService { @Override @SuppressWarnings("unchecked") public boolean hasPermission(SecurityUser user, Resource resource, Operation operation) throws ThingsboardException { - PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); - if (permissionChecker != null) { - return permissionChecker.hasPermission(user, operation); - } - return false; + var permissionChecker = getPermissionChecker(user.getAuthority(), resource); + return permissionChecker.hasPermission(user, operation); } @Override @@ -78,11 +75,8 @@ public class DefaultAccessControlService implements AccessControlService { @Override @SuppressWarnings("unchecked") public boolean hasPermission(SecurityUser user, Resource resource, Operation operation, I entityId, T entity) throws ThingsboardException { - PermissionChecker permissionChecker = getPermissionChecker(user.getAuthority(), resource); - if (permissionChecker != null) { - return permissionChecker.hasPermission(user, operation, entityId, entity); - } - return false; + var permissionChecker = getPermissionChecker(user.getAuthority(), resource); + return permissionChecker.hasPermission(user, operation, entityId, entity); } private PermissionChecker getPermissionChecker(Authority authority, Resource resource) throws ThingsboardException { From 287e6b950e8b97bf223530dc693beda08ad5344b Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 5 Dec 2025 13:00:01 +0200 Subject: [PATCH 6/7] fixed UserController getUsersByIds method --- .../java/org/thingsboard/server/controller/UserController.java | 2 +- .../org/thingsboard/server/controller/UserControllerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 8da3978aeb..27a55353ba 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -599,7 +599,7 @@ public class UserController extends BaseController { @ApiOperation(value = "Get Users By Ids (getUsersByIds)", notes = "Requested users must be owned by tenant or assigned to customer which user is performing the request. ") - @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/users", params = {"userIds"}) public List getUsersByIds( @Parameter(description = "A list of user ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) diff --git a/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java index 4379b57b45..f5f51a0c6b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java @@ -269,7 +269,7 @@ public class UserControllerTest extends AbstractControllerTest { @Test public void testFindUsersByIds() throws Exception { - loginSysAdmin(); + loginTenantAdmin(); List savedUsers = new ArrayList<>(); for (int i = 0; i < 10; i++) { User user = createTenantAdminUser(); From d62355e4bda4ceeb0061115d4a5f4fe67d450853 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 8 Dec 2025 14:17:09 +0200 Subject: [PATCH 7/7] refactoring --- .../controller/AssetProfileController.java | 17 ++++++-------- .../server/controller/CustomerController.java | 17 ++++++-------- .../controller/DashboardController.java | 13 ++++------- .../controller/DeviceProfileController.java | 23 +++++++------------ .../controller/EntityViewController.java | 14 +++++------ .../controller/RuleChainController.java | 14 +++++------ .../server/controller/TenantController.java | 17 ++++++-------- .../server/controller/UserController.java | 16 ++++++------- .../controller/WidgetsBundleController.java | 17 ++++---------- .../server/dao/asset/AssetProfileService.java | 3 +-- .../server/dao/customer/CustomerService.java | 2 +- .../dao/dashboard/DashboardService.java | 2 +- .../dao/device/DeviceProfileService.java | 3 +-- .../dao/entityview/EntityViewService.java | 2 +- .../server/dao/rule/RuleChainService.java | 2 +- .../server/dao/tenant/TenantService.java | 2 +- .../server/dao/user/UserService.java | 2 +- .../dao/widget/WidgetsBundleService.java | 5 +--- .../server/dao/asset/AssetProfileDao.java | 3 +-- .../dao/asset/AssetProfileServiceImpl.java | 10 +++----- .../server/dao/customer/CustomerDao.java | 3 +-- .../dao/customer/CustomerServiceImpl.java | 9 +++----- .../dao/dashboard/DashboardInfoDao.java | 3 +-- .../dao/dashboard/DashboardServiceImpl.java | 8 +++---- .../server/dao/device/DeviceProfileDao.java | 3 +-- .../dao/device/DeviceProfileServiceImpl.java | 10 +++----- .../server/dao/entityview/EntityViewDao.java | 2 +- .../dao/entityview/EntityViewServiceImpl.java | 9 +++----- .../server/dao/rule/BaseRuleChainService.java | 8 +++---- .../server/dao/rule/RuleChainDao.java | 4 +--- .../dao/sql/asset/JpaAssetProfileDao.java | 5 ++-- .../dao/sql/customer/JpaCustomerDao.java | 5 ++-- .../sql/dashboard/JpaDashboardInfoDao.java | 4 ++-- .../dao/sql/device/JpaDeviceProfileDao.java | 5 ++-- .../dao/sql/entityview/JpaEntityViewDao.java | 4 ++-- .../server/dao/sql/rule/JpaRuleChainDao.java | 5 ++-- .../server/dao/sql/tenant/JpaTenantDao.java | 5 ++-- .../server/dao/sql/user/JpaUserDao.java | 5 ++-- .../dao/sql/widget/JpaWidgetsBundleDao.java | 11 ++------- .../sql/widget/WidgetsBundleRepository.java | 16 ++++--------- .../server/dao/tenant/TenantDao.java | 3 +-- .../server/dao/tenant/TenantServiceImpl.java | 7 +++--- .../thingsboard/server/dao/user/UserDao.java | 3 +-- .../server/dao/user/UserServiceImpl.java | 9 +++----- .../server/dao/widget/WidgetsBundleDao.java | 5 +--- .../dao/widget/WidgetsBundleServiceImpl.java | 19 +++------------ 46 files changed, 127 insertions(+), 227 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index 9c12880e96..59cec67be6 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -48,9 +48,9 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.concurrent.ExecutionException; +import java.util.Set; +import java.util.UUID; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID_PARAM_DESCRIPTION; @@ -234,16 +234,13 @@ public class AssetProfileController extends BaseController { @GetMapping(value = "/assetProfileInfos", params = {"assetProfileIds"}) public List getAssetProfilesByIds( @Parameter(description = "A list of asset profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("assetProfileIds") String[] strAssetProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("assetProfileIds", strAssetProfileIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("assetProfileIds") Set assetProfileUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List assetProfileIds = new ArrayList<>(); - for (String strAssetProfileId : strAssetProfileIds) { - assetProfileIds.add(new AssetProfileId(toUUID(strAssetProfileId))); + for (UUID assetProfileUUID : assetProfileUUIDs) { + assetProfileIds.add(new AssetProfileId(assetProfileUUID)); } - - return assetProfileService.findAssetProfilesByIdsAsync(tenantId, assetProfileIds).get(); + return assetProfileService.findAssetProfilesByIds(tenantId, assetProfileIds); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index ad547d3cc3..67ce9cc7c4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -42,14 +42,13 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.customer.TbCustomerService; -import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.concurrent.ExecutionException; +import java.util.Set; +import java.util.UUID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; @@ -198,15 +197,13 @@ public class CustomerController extends BaseController { @GetMapping(value = "/customers", params = {"customerIds"}) public List getCustomersByIds( @Parameter(description = "A list of customer ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("customerIds") String[] strCustomerIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("customerIds", strCustomerIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("customerIds") Set customerUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List customerIds = new ArrayList<>(); - for (String strCustomerId : strCustomerIds) { - customerIds.add(new CustomerId(toUUID(strCustomerId))); + for (UUID customerUUID : customerUUIDs) { + customerIds.add(new CustomerId(customerUUID)); } - return customerService.findCustomersByTenantIdAndIdsAsync(tenantId, customerIds).get(); + return customerService.findCustomersByTenantIdAndIds(tenantId, customerIds); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index f23c3d3e19..fe5ba633db 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -70,7 +70,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @@ -621,15 +620,13 @@ public class DashboardController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/dashboards", params = {"dashboardIds"}) public List getDashboardsByIds(@Parameter(description = "A list of dashboard ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("dashboardIds") String[] strDashboardIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("dashboardIds", strDashboardIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("dashboardIds") Set dashboardUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List dashboardIds = new ArrayList<>(); - for (String strDashboardId : strDashboardIds) { - dashboardIds.add(new DashboardId(toUUID(strDashboardId))); + for (UUID dashboardUUID : dashboardUUIDs) { + dashboardIds.add(new DashboardId(dashboardUUID)); } - List dashboards = checkNotNull(dashboardService.findDashboardInfoByIdsAsync(tenantId, dashboardIds).get()); + List dashboards = dashboardService.findDashboardInfoByIds(tenantId, dashboardIds); return filterDashboardsByReadPermission(dashboards); } diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index 7092a48c59..9ead0c099d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -51,10 +51,9 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.UUID; -import java.util.concurrent.ExecutionException; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_DATA; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID; @@ -283,26 +282,20 @@ public class DeviceProfileController extends BaseController { return checkNotNull(deviceProfileService.findDeviceProfileNamesByTenantId(tenantId, activeOnly)); } - @ApiOperation(value = "Get Device Profiles By Ids (getDeviceProfilesByIds)", + @ApiOperation(value = "Get Device Profile Infos By Ids (getDeviceProfilesByIds)", notes = "Requested device profiles must be owned by tenant which is performing the request. " + NEW_LINE) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @GetMapping(value = "/deviceProfileInfos", params = {"deviceProfileIds"}) - public List getDeviceProfilesByIds( + public List getDeviceProfileInfosByIds( @Parameter(description = "A list of device profile ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("deviceProfileIds") String[] strDeviceProfileIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("deviceProfileIds", strDeviceProfileIds); - SecurityUser user = getCurrentUser(); - if (!accessControlService.hasPermission(user, Resource.DEVICE_PROFILE, Operation.READ)) { - return Collections.emptyList(); - } - TenantId tenantId = user.getTenantId(); + @RequestParam("deviceProfileIds") Set deviceProfileUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List deviceProfileIds = new ArrayList<>(); - for (String strDeviceProfileId : strDeviceProfileIds) { - deviceProfileIds.add(new DeviceProfileId(toUUID(strDeviceProfileId))); + for (UUID deviceProfileUUID : deviceProfileUUIDs) { + deviceProfileIds.add(new DeviceProfileId(deviceProfileUUID)); } - - return checkNotNull(deviceProfileService.findDeviceProfilesByIdsAsync(tenantId, deviceProfileIds).get()); + return deviceProfileService.findDeviceProfilesByIds(tenantId, deviceProfileIds); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index c67f260422..4455843b99 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -57,6 +57,8 @@ import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; @@ -468,15 +470,13 @@ public class EntityViewController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/entityViews", params = {"entityViewIds"}) public List getEntityViewsByIds(@Parameter(description = "A list of entity view ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("entityViewIds") String[] strEntityViewIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("entityViewIds", strEntityViewIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("entityViewIds") Set entityViewUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List entityViewIds = new ArrayList<>(); - for (String strEntityViewId : strEntityViewIds) { - entityViewIds.add(new EntityViewId(toUUID(strEntityViewId))); + for (UUID entityViewUUID : entityViewUUIDs) { + entityViewIds.add(new EntityViewId(entityViewUUID)); } - List entityViews = checkNotNull(entityViewService.findEntityViewsByTenantIdAndIdsAsync(tenantId, entityViewIds).get()); + List entityViews = entityViewService.findEntityViewsByTenantIdAndIds(tenantId, entityViewIds); return filterEntityViewsByReadPermission(entityViews); } diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index c1aa3acc89..bbc5ef2195 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -72,7 +72,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.rule.TbRuleChainService; import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; import org.thingsboard.server.service.script.RuleNodeTbelScriptEngine; -import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; @@ -81,6 +80,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; @@ -589,15 +589,13 @@ public class RuleChainController extends BaseController { @GetMapping(value = "/ruleChains", params = {"ruleChainIds"}) public List getRuleChainsByIds( @Parameter(description = "A list of rule chain ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("ruleChainIds") String[] strRuleChainIds) throws Exception { - checkArrayParameter("ruleChainIds", strRuleChainIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("ruleChainIds") Set ruleChainUUIDs) throws Exception { + TenantId tenantId = getCurrentUser().getTenantId(); List ruleChainIds = new ArrayList<>(); - for (String strRuleChainId : strRuleChainIds) { - ruleChainIds.add(new RuleChainId(toUUID(strRuleChainId))); + for (UUID ruleChainUUID : ruleChainUUIDs) { + ruleChainIds.add(new RuleChainId(ruleChainUUID)); } - return ruleChainService.findRuleChainsByIdsAsync(tenantId, ruleChainIds).get(); + return ruleChainService.findRuleChainsByIds(tenantId, ruleChainIds); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantController.java b/application/src/main/java/org/thingsboard/server/controller/TenantController.java index 8187b3018e..7eeb8c7416 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantController.java @@ -41,14 +41,13 @@ import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.tenant.TbTenantService; -import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.concurrent.ExecutionException; +import java.util.Set; +import java.util.UUID; import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; @@ -178,15 +177,13 @@ public class TenantController extends BaseController { @GetMapping(value = "/tenants", params = {"tenantIds"}) public List getTenantsByIds( @Parameter(description = "A list of tenant ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string"))) - @RequestParam("tenantIds") String[] strTenantIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("tenantIds", strTenantIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("tenantIds") Set tenantUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List tenantIds = new ArrayList<>(); - for (String strTenantId : strTenantIds) { - tenantIds.add(new TenantId(toUUID(strTenantId))); + for (UUID tenantIdUUID : tenantUUIDs) { + tenantIds.add(TenantId.fromUUID(tenantIdUUID)); } - return tenantService.findTenantsByIdsAsync(tenantId, tenantIds).get(); + return tenantService.findTenantsByIds(tenantId, tenantIds); } } 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 27a55353ba..6ec1717745 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -85,8 +85,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ExecutionException; +import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; @@ -603,15 +603,13 @@ public class UserController extends BaseController { @GetMapping(value = "/users", params = {"userIds"}) public List getUsersByIds( @Parameter(description = "A list of user ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("userIds") String[] strUserIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("userIds", strUserIds); - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); + @RequestParam("userIds") Set userUUIDs) throws ThingsboardException { + TenantId tenantId = getCurrentUser().getTenantId(); List userIds = new ArrayList<>(); - for (String strUserId : strUserIds) { - userIds.add(new UserId(toUUID(strUserId))); + for (UUID userUUID : userUUIDs) { + userIds.add(new UserId(userUUID)); } - List users = checkNotNull(userService.findUsersByTenantIdAndIdsAsync(tenantId, userIds).get()); + List users = userService.findUsersByTenantIdAndIds(tenantId, userIds); return filterUsersByReadPermission(users); } diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 021aaf9d13..cc39d47a9b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -47,12 +47,10 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.ArrayList; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; -import java.util.Objects; import java.util.Set; -import java.util.concurrent.ExecutionException; +import java.util.UUID; import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER; import static org.thingsboard.server.controller.ControllerConstants.INLINE_IMAGES; @@ -247,17 +245,12 @@ public class WidgetsBundleController extends BaseController { @GetMapping(value = "/widgetsBundles", params = {"widgetsBundleIds"}) public List getWidgetsBundlesByIds( @Parameter(description = "A list of widgets bundle ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) - @RequestParam("widgetsBundleIds") String[] strWidgetsBundleIds) throws ThingsboardException, ExecutionException, InterruptedException { - checkArrayParameter("widgetsBundleIds", strWidgetsBundleIds); + @RequestParam("widgetsBundleIds") Set widgetsBundleUUIDs) throws ThingsboardException { List widgetsBundleIds = new ArrayList<>(); - for (String strWidgetsBundleId : strWidgetsBundleIds) { - widgetsBundleIds.add(new WidgetsBundleId(toUUID(strWidgetsBundleId))); - } - if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { - return widgetsBundleService.findSystemWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get(); - } else { - return widgetsBundleService.findAllTenantWidgetsBundlesByIdsAsync(getTenantId(), widgetsBundleIds).get(); + for (UUID widgetsBundleUUID : widgetsBundleUUIDs) { + widgetsBundleIds.add(new WidgetsBundleId(widgetsBundleUUID)); } + return widgetsBundleService.findSystemOrTenantWidgetsBundlesByIds(getTenantId(), widgetsBundleIds); } } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java index e867656d4c..bc7af698f9 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/asset/AssetProfileService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.asset; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.asset.AssetProfileInfo; @@ -63,6 +62,6 @@ public interface AssetProfileService extends EntityDaoService { List findAssetProfileNamesByTenantId(TenantId tenantId, boolean activeOnly); - ListenableFuture> findAssetProfilesByIdsAsync(TenantId tenantId, List assetProfileIds); + List findAssetProfilesByIds(TenantId tenantId, List assetProfileIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java index 82a5605409..a494313291 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/customer/CustomerService.java @@ -48,6 +48,6 @@ public interface CustomerService extends EntityDaoService { void deleteCustomersByTenantId(TenantId tenantId); - ListenableFuture> findCustomersByTenantIdAndIdsAsync(TenantId tenantId, List customerIds); + List findCustomersByTenantIdAndIds(TenantId tenantId, List customerIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java index 18efebc92d..1d850ac99b 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/dashboard/DashboardService.java @@ -80,6 +80,6 @@ public interface DashboardService extends EntityDaoService { PageData findAllDashboardsIds(PageLink pageLink); - ListenableFuture> findDashboardInfoByIdsAsync(TenantId tenantId, List dashboardIds); + List findDashboardInfoByIds(TenantId tenantId, List dashboardIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java index 3bbd760eec..81fdcffb3f 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.device; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileInfo; import org.thingsboard.server.common.data.EntityInfo; @@ -65,6 +64,6 @@ public interface DeviceProfileService extends EntityDaoService { List findDeviceProfileNamesByTenantId(TenantId tenantId, boolean activeOnly); - ListenableFuture> findDeviceProfilesByIdsAsync(TenantId tenantId, List deviceProfileIds); + List findDeviceProfilesByIds(TenantId tenantId, List deviceProfileIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java index e64cd0dd6d..ee2ef71557 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java @@ -65,7 +65,7 @@ public interface EntityViewService extends EntityDaoService { PageData findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); - ListenableFuture> findEntityViewsByTenantIdAndIdsAsync(TenantId tenantId, List entityViewIds); + List findEntityViewsByTenantIdAndIds(TenantId tenantId, List entityViewIds); PageData findEntityViewInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java index fd84cc4c82..faeeae0244 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java @@ -117,6 +117,6 @@ public interface RuleChainService extends EntityDaoService { void deleteRuleNodes(TenantId tenantId, RuleChainId ruleChainId); - ListenableFuture> findRuleChainsByIdsAsync(TenantId tenantId, List ruleChainIds); + List findRuleChainsByIds(TenantId tenantId, List ruleChainIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java index db9b77e161..d54f46de59 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantService.java @@ -55,6 +55,6 @@ public interface TenantService extends EntityDaoService { PageData findTenantsIds(PageLink pageLink); - ListenableFuture> findTenantsByIdsAsync(TenantId callerId, List tenantIds); + List findTenantsByIds(TenantId callerId, List tenantIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java index 629f1c1db5..d911f69bc7 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java @@ -111,6 +111,6 @@ public interface UserService extends EntityDaoService { int countTenantAdmins(TenantId tenantId); - ListenableFuture> findUsersByTenantIdAndIdsAsync(TenantId tenantId, List userIds); + List findUsersByTenantIdAndIds(TenantId tenantId, List userIds); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java index 5341b8862b..4c5d7cb086 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.widget; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.page.PageData; @@ -53,8 +52,6 @@ public interface WidgetsBundleService extends EntityDaoService { void updateSystemWidgets(Stream bundles, Stream widgets); - ListenableFuture> findSystemWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds); - - ListenableFuture> findAllTenantWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds); + List findSystemOrTenantWidgetsBundlesByIds(TenantId tenantId, List widgetsBundleIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java index d56e794b93..e12ca07999 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.asset; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.asset.AssetProfileInfo; @@ -52,6 +51,6 @@ public interface AssetProfileDao extends Dao, ExportableEntityDao< List findTenantAssetProfileNames(UUID tenantId, boolean activeOnly); - ListenableFuture> findAssetProfilesByTenantIdAndIdsAsync(UUID tenantId, List assetProfileIds); + List findAssetProfilesByTenantIdAndIds(UUID tenantId, List assetProfileIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index 63a5e1b241..86f3cfe130 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.asset; import com.google.common.util.concurrent.FluentFuture; -import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.hibernate.exception.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; @@ -54,7 +53,6 @@ import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("AssetProfileDaoService") @Slf4j @@ -349,11 +347,9 @@ public class AssetProfileServiceImpl extends CachedVersionedEntityService> findAssetProfilesByIdsAsync(TenantId tenantId, List assetProfileIds) { - log.trace("Executing findAssetProfilesByIdsAsync, tenantId [{}], assetProfileIds [{}]", tenantId, assetProfileIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(assetProfileIds, ids -> "Incorrect assetProfileIds " + ids); - return assetProfileDao.findAssetProfilesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(assetProfileIds)); + public List findAssetProfilesByIds(TenantId tenantId, List assetProfileIds) { + log.trace("Executing findAssetProfilesByIds, tenantId [{}], assetProfileIds [{}]", tenantId, assetProfileIds); + return assetProfileDao.findAssetProfilesByTenantIdAndIds(tenantId.getId(), toUUIDs(assetProfileIds)); } private final PaginatedRemover tenantAssetProfilesRemover = diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java index 9b3a22eaaa..7b039a6dfd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.customer; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -80,6 +79,6 @@ public interface CustomerDao extends Dao, TenantEntityDao, E */ PageData findCustomersWithTheSameTitle(PageLink pageLink); - ListenableFuture> findCustomersByTenantIdAndIdsAsync(UUID tenantId, List customerIds); + List findCustomersByTenantIdAndIds(UUID tenantId, List customerIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java index 10299e3223..196cd468ca 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/customer/CustomerServiceImpl.java @@ -59,7 +59,6 @@ import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("CustomerDaoService") @Slf4j @@ -266,11 +265,9 @@ public class CustomerServiceImpl extends AbstractCachedEntityService> findCustomersByTenantIdAndIdsAsync(TenantId tenantId, List customerIds) { - log.trace("Executing findCustomersByTenantIdAndIdsAsync, tenantId [{}], customerIds [{}]", tenantId, customerIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(customerIds, ids -> "Incorrect customerIds " + ids); - return customerDao.findCustomersByTenantIdAndIdsAsync(tenantId.getId(), customerIds.stream().map(CustomerId::getId).collect(Collectors.toList())); + public List findCustomersByTenantIdAndIds(TenantId tenantId, List customerIds) { + log.trace("Executing findCustomersByTenantIdAndIds, tenantId [{}], customerIds [{}]", tenantId, customerIds); + return customerDao.findCustomersByTenantIdAndIds(tenantId.getId(), customerIds.stream().map(CustomerId::getId).collect(Collectors.toList())); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java index 3687c01d02..698eb159bf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.dashboard; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; @@ -83,6 +82,6 @@ public interface DashboardInfoDao extends Dao, ImageContainerDao< String findTitleById(UUID tenantId, UUID dashboardId); - ListenableFuture> findDashboardsByIdsAsync(UUID tenantId, List dashboardIds); + List findDashboardsByIds(UUID tenantId, List dashboardIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java index 7838c1a717..ae2186243d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java @@ -65,7 +65,6 @@ import java.util.Optional; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("DashboardDaoService") @Slf4j @@ -412,10 +411,9 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb } @Override - public ListenableFuture> findDashboardInfoByIdsAsync(TenantId tenantId, List dashboardIds) { - log.trace("Executing findDashboardInfoByIdsAsync, dashboardIds [{}]", dashboardIds); - validateIds(dashboardIds, ids -> "Incorrect dashboardIds " + ids); - return dashboardInfoDao.findDashboardsByIdsAsync(tenantId.getId(), toUUIDs(dashboardIds)); + public List findDashboardInfoByIds(TenantId tenantId, List dashboardIds) { + log.trace("Executing findDashboardInfoByIds, dashboardIds [{}]", dashboardIds); + return dashboardInfoDao.findDashboardsByIds(tenantId.getId(), toUUIDs(dashboardIds)); } private final PaginatedRemover tenantDashboardsRemover = new PaginatedRemover<>() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java index 470881a690..699d8fe595 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.device; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileInfo; import org.thingsboard.server.common.data.EntityInfo; @@ -54,6 +53,6 @@ public interface DeviceProfileDao extends Dao, ExportableEntityDa List findTenantDeviceProfileNames(UUID tenantId, boolean activeOnly); - ListenableFuture> findDeviceProfilesByTenantIdAndIdsAsync(UUID tenantId, List deviceProfileIds); + List findDeviceProfilesByTenantIdAndIds(UUID tenantId, List deviceProfileIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java index eddf18e3c2..612be215e5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.device; import com.google.common.util.concurrent.FluentFuture; -import com.google.common.util.concurrent.ListenableFuture; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -69,7 +68,6 @@ import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validateString; @Service("DeviceProfileDaoService") @@ -395,11 +393,9 @@ public class DeviceProfileServiceImpl extends CachedVersionedEntityService> findDeviceProfilesByIdsAsync(TenantId tenantId, List deviceProfileIds) { - log.trace("Executing findDeviceProfilesByIdsAsync, tenantId [{}], deviceProfileIds [{}]", tenantId, deviceProfileIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(deviceProfileIds, ids -> "Incorrect deviceProfileIds " + ids); - return deviceProfileDao.findDeviceProfilesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(deviceProfileIds)); + public List findDeviceProfilesByIds(TenantId tenantId, List deviceProfileIds) { + log.trace("Executing findDeviceProfilesByIds, tenantId [{}], deviceProfileIds [{}]", tenantId, deviceProfileIds); + return deviceProfileDao.findDeviceProfilesByTenantIdAndIds(tenantId.getId(), toUUIDs(deviceProfileIds)); } private final PaginatedRemover tenantDeviceProfilesRemover = diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java index 52d077a3bb..58fc740bd7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java @@ -169,7 +169,7 @@ public interface EntityViewDao extends Dao, ExportableEntityDao> findEntityViewsByTenantIdAndIdsAsync(UUID tenantId, List entityViewIds); + List findEntityViewsByTenantIdAndIds(UUID tenantId, List entityViewIds); /** * Find entity views by tenantId, edgeId, type and page link. diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index e135555659..43bdd515fa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -64,7 +64,6 @@ import java.util.stream.Collectors; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validatePageLink; import static org.thingsboard.server.dao.service.Validator.validateString; @@ -258,11 +257,9 @@ public class EntityViewServiceImpl extends CachedVersionedEntityService> findEntityViewsByTenantIdAndIdsAsync(TenantId tenantId, List entityViewIds) { - log.trace("Executing findEntityViewsByTenantIdAndIdsAsync, tenantId [{}], entityViewIds [{}]", tenantId, entityViewIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(entityViewIds, ids -> "Incorrect entityViewIds " + ids); - return entityViewDao.findEntityViewsByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(entityViewIds)); + public List findEntityViewsByTenantIdAndIds(TenantId tenantId, List entityViewIds) { + log.trace("Executing findEntityViewsByTenantIdAndIds, tenantId [{}], entityViewIds [{}]", tenantId, entityViewIds); + return entityViewDao.findEntityViewsByTenantIdAndIds(tenantId.getId(), toUUIDs(entityViewIds)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index c1561084b9..23e0b4b30d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -871,11 +871,9 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC } @Override - public ListenableFuture> findRuleChainsByIdsAsync(TenantId tenantId, List ruleChainIds) { - log.trace("Executing findRuleChainsByIdsAsync, tenantId [{}], ruleChainIds [{}]", tenantId, ruleChainIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(ruleChainIds, ids -> "Incorrect ruleChainIds " + ids); - return ruleChainDao.findRuleChainsByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(ruleChainIds)); + public List findRuleChainsByIds(TenantId tenantId, List ruleChainIds) { + log.trace("Executing findRuleChainsByIds, tenantId [{}], ruleChainIds [{}]", tenantId, ruleChainIds); + return ruleChainDao.findRuleChainsByTenantIdAndIds(tenantId.getId(), toUUIDs(ruleChainIds)); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java index 7b4e9a7fb9..b8c95656f1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java @@ -15,14 +15,12 @@ */ package org.thingsboard.server.dao.rule; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainType; -import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.ExportableEntityDao; import org.thingsboard.server.dao.ResourceContainerDao; @@ -85,6 +83,6 @@ public interface RuleChainDao extends Dao, TenantEntityDao Collection findByTenantIdAndTypeAndName(TenantId tenantId, RuleChainType type, String name); - ListenableFuture> findRuleChainsByTenantIdAndIdsAsync(UUID tenantId, List ruleChainIds); + List findRuleChainsByTenantIdAndIds(UUID tenantId, List ruleChainIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java index 99093827e5..8ea5078b9a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.asset; -import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.domain.PageRequest; @@ -107,8 +106,8 @@ public class JpaAssetProfileDao extends JpaAbstractDao> findAssetProfilesByTenantIdAndIdsAsync(UUID tenantId, List assetProfileIds) { - return service.submit(() -> assetProfileRepository.findAssetProfileInfosByTenantIdAndIdIn(tenantId, assetProfileIds)); + public List findAssetProfilesByTenantIdAndIds(UUID tenantId, List assetProfileIds) { + return assetProfileRepository.findAssetProfileInfosByTenantIdAndIdIn(tenantId, assetProfileIds); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java index d1a31faaaf..d358f887cd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.customer; -import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -109,8 +108,8 @@ public class JpaCustomerDao extends JpaAbstractDao imp } @Override - public ListenableFuture> findCustomersByTenantIdAndIdsAsync(UUID tenantId, List customerIds) { - return service.submit(() -> DaoUtil.convertDataList(customerRepository.findCustomersByTenantIdAndIdIn(tenantId, customerIds))); + public List findCustomersByTenantIdAndIds(UUID tenantId, List customerIds) { + return DaoUtil.convertDataList(customerRepository.findCustomersByTenantIdAndIdIn(tenantId, customerIds)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java index f3999a10c6..f0c164d9d4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java @@ -128,8 +128,8 @@ public class JpaDashboardInfoDao extends JpaAbstractDao> findDashboardsByIdsAsync(UUID tenantId, List dashboardIds) { - return service.submit(() -> DaoUtil.convertDataList(dashboardInfoRepository.findByIdIn(dashboardIds))); + public List findDashboardsByIds(UUID tenantId, List dashboardIds) { + return DaoUtil.convertDataList(dashboardInfoRepository.findByIdIn(dashboardIds)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java index 41dbf3978e..732b44efc2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.device; -import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.domain.PageRequest; @@ -125,8 +124,8 @@ public class JpaDeviceProfileDao extends JpaAbstractDao> findDeviceProfilesByTenantIdAndIdsAsync(UUID tenantId, List deviceProfileIds) { - return service.submit(() -> deviceProfileRepository.findDeviceProfileInfosByTenantIdAndIdIn(tenantId, deviceProfileIds)); + public List findDeviceProfilesByTenantIdAndIds(UUID tenantId, List deviceProfileIds) { + return deviceProfileRepository.findDeviceProfileInfosByTenantIdAndIdIn(tenantId, deviceProfileIds); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index fe3f63825f..b03c9a4dcf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -188,8 +188,8 @@ public class JpaEntityViewDao extends JpaAbstractDao> findEntityViewsByTenantIdAndIdsAsync(UUID tenantId, List entityViewIds) { - return service.submit(() -> DaoUtil.convertDataList(entityViewRepository.findEntityViewsByTenantIdAndIdIn(tenantId, entityViewIds))); + public List findEntityViewsByTenantIdAndIds(UUID tenantId, List entityViewIds) { + return DaoUtil.convertDataList(entityViewRepository.findEntityViewsByTenantIdAndIdIn(tenantId, entityViewIds)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java index f541627309..43db265d5b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.rule; -import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; @@ -114,8 +113,8 @@ public class JpaRuleChainDao extends JpaAbstractDao } @Override - public ListenableFuture> findRuleChainsByTenantIdAndIdsAsync(UUID tenantId, List ruleChainIds) { - return service.submit(() -> DaoUtil.convertDataList(ruleChainRepository.findRuleChainsByTenantIdAndIdIn(tenantId, ruleChainIds))); + public List findRuleChainsByTenantIdAndIds(UUID tenantId, List ruleChainIds) { + return DaoUtil.convertDataList(ruleChainRepository.findRuleChainsByTenantIdAndIdIn(tenantId, ruleChainIds)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java index 781753bb7d..94597bbfcb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.tenant; -import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -100,8 +99,8 @@ public class JpaTenantDao extends JpaAbstractDao implement } @Override - public ListenableFuture> findTenantsByIdsAsync(UUID tenantId, List tenantIds) { - return service.submit(() -> DaoUtil.convertDataList(tenantRepository.findTenantsByIdIn(tenantIds))); + public List findTenantsByIds(UUID tenantId, List tenantIds) { + return DaoUtil.convertDataList(tenantRepository.findTenantsByIdIn(tenantIds)); } @Override 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 3b3f4dc15c..576bae8da4 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 @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.user; -import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -143,8 +142,8 @@ public class JpaUserDao extends JpaAbstractDao implements User } @Override - public ListenableFuture> findUsersByTenantIdAndIdsAsync(UUID tenantId, List userIds) { - return service.submit(() -> DaoUtil.convertDataList(userRepository.findUsersByTenantIdAndIdIn(tenantId, userIds))); + public List findUsersByTenantIdAndIds(UUID tenantId, List userIds) { + return DaoUtil.convertDataList(userRepository.findUsersByTenantIdAndIdIn(tenantId, userIds)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java index b1481d636a..aa4ce77fec 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.widget; -import com.google.common.util.concurrent.ListenableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Limit; import org.springframework.data.jpa.repository.JpaRepository; @@ -113,14 +112,8 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao> findSystemWidgetBundlesByIdsAsync(UUID tenantId, List widgetsBundleIds) { - return service.submit(() -> DaoUtil.convertDataList(widgetsBundleRepository.findSystemWidgetsBundlesByIdIn(NULL_UUID, widgetsBundleIds))); - } - - @Override - public ListenableFuture> findAllTenantWidgetBundlesByTenantIdAndIdsAsync(UUID tenantId, List widgetsBundleIds) { - return service.submit(() -> DaoUtil.convertDataList(widgetsBundleRepository - .findAllTenantWidgetsBundlesByTenantIdAndIdIn(tenantId, NULL_UUID, widgetsBundleIds))); + public List findSystemOrTenantWidgetBundlesByIds(UUID tenantId, List widgetsBundleIds) { + return DaoUtil.convertDataList(widgetsBundleRepository.findSystemOrTenantWidgetsBundlesByIdIn(tenantId, TenantId.NULL_UUID, widgetsBundleIds)); } private PageData findTenantWidgetsBundlesByTenantIds(List tenantIds, WidgetsBundleFilter widgetsBundleFilter, PageLink pageLink) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java index 53053eb3c0..1479f29e71 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java @@ -21,7 +21,6 @@ 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.edqs.fields.WidgetTypeFields; import org.thingsboard.server.common.data.edqs.fields.WidgetsBundleFields; import org.thingsboard.server.dao.ExportableEntityRepository; import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; @@ -147,15 +146,10 @@ public interface WidgetsBundleRepository extends JpaRepository :id ORDER BY w.id") List findNextBatch(@Param("id") UUID id, Limit limit); - @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :systemTenantId " + - "AND wb.id IN :widgetsBundleIds") - List findSystemWidgetsBundlesByIdIn(@Param("systemTenantId") UUID systemTenantId, - @Param("widgetsBundleIds") List widgetsBundleIds); - - @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId IN (:tenantId, :nullTenantId) " + - "AND wb.id IN :widgetsBundleIds") - List findAllTenantWidgetsBundlesByTenantIdAndIdIn(@Param("tenantId") UUID tenantId, - @Param("nullTenantId") UUID nullTenantId, - @Param("widgetsBundleIds") List widgetsBundleIds); + @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE " + + "wb.id IN (:widgetsBundleIds) AND (wb.tenantId = :tenantId OR wb.tenantId = :systemTenantId)") + List findSystemOrTenantWidgetsBundlesByIdIn(@Param("tenantId") UUID tenantId, + @Param("systemTenantId") UUID systemTenantId, + @Param("widgetsBundleIds") List widgetsBundleIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java index 5bab7e6295..94ea13e34e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.tenant; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantInfo; import org.thingsboard.server.common.data.id.TenantId; @@ -43,6 +42,6 @@ public interface TenantDao extends Dao { Tenant findTenantByName(TenantId tenantId, String name); - ListenableFuture> findTenantsByIdsAsync(UUID tenantId, List tenantIds); + List findTenantsByIds(UUID tenantId, List tenantIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index a6f8bac498..b2c74a01e8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -227,10 +227,9 @@ public class TenantServiceImpl extends AbstractCachedEntityService> findTenantsByIdsAsync(TenantId callerId, List tenantIds) { - log.trace("Executing findTenantsByIdsAsync, callerId [{}], tenantIds [{}]", callerId, tenantIds); - validateIds(tenantIds, ids -> "Incorrect tenantIds " + ids); - return tenantDao.findTenantsByIdsAsync(callerId.getId(), toUUIDs(tenantIds)); + public List findTenantsByIds(TenantId callerId, List tenantIds) { + log.trace("Executing findTenantsByIds, callerId [{}], tenantIds [{}]", callerId, tenantIds); + return tenantDao.findTenantsByIds(callerId.getId(), toUUIDs(tenantIds)); } @Override 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 26e98a4edf..99b9808d08 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 @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.user; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -104,6 +103,6 @@ public interface UserDao extends Dao, TenantEntityDao { int countTenantAdmins(UUID tenantId); - ListenableFuture> findUsersByTenantIdAndIdsAsync(UUID tenantId, List userIds); + List findUsersByTenantIdAndIds(UUID tenantId, List userIds); } 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 dbf3c72c5b..a8d3a418af 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 @@ -77,7 +77,6 @@ import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.common.data.StringUtils.generateSafeToken; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; import static org.thingsboard.server.dao.service.Validator.validatePageLink; import static org.thingsboard.server.dao.service.Validator.validateString; @@ -495,11 +494,9 @@ public class UserServiceImpl extends AbstractCachedEntityService> findUsersByTenantIdAndIdsAsync(TenantId tenantId, List userIds) { - log.trace("Executing findUsersByTenantIdAndIdsAsync, tenantId [{}], userIds [{}]", tenantId, userIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(userIds, ids -> "Incorrect userIds " + ids); - return userDao.findUsersByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(userIds)); + public List findUsersByTenantIdAndIds(TenantId tenantId, List userIds) { + log.trace("Executing findUsersByTenantIdAndIds, tenantId [{}], userIds [{}]", tenantId, userIds); + return userDao.findUsersByTenantIdAndIds(tenantId.getId(), toUUIDs(userIds)); } private Optional findMobileSessionInfo(TenantId tenantId, UserId userId) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java index b9e03072b1..562cdc29c3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.widget; -import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.page.PageData; @@ -89,9 +88,7 @@ public interface WidgetsBundleDao extends Dao, ExportableEntityDa PageData findAllWidgetsBundles(PageLink pageLink); - ListenableFuture> findSystemWidgetBundlesByIdsAsync(UUID tenantId, List widgetsBundleIds); - - ListenableFuture> findAllTenantWidgetBundlesByTenantIdAndIdsAsync(UUID tenantId, List widgetsBundleIds); + List findSystemOrTenantWidgetBundlesByIds(UUID tenantId, List widgetsBundleIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java index 5d4b6d4bb0..a98e9b78eb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java @@ -17,7 +17,6 @@ package org.thingsboard.server.dao.widget; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.FluentFuture; -import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; @@ -51,8 +50,6 @@ import java.util.stream.Stream; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.dao.DaoUtil.toUUIDs; import static org.thingsboard.server.dao.entity.AbstractEntityService.checkConstraintViolation; -import static org.thingsboard.server.dao.service.Validator.validateId; -import static org.thingsboard.server.dao.service.Validator.validateIds; @Service("WidgetsBundleDaoService") @Slf4j @@ -257,19 +254,9 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService { } @Override - public ListenableFuture> findSystemWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds) { - log.trace("Executing findSystemWidgetsBundlesByIdsAsync, tenantId [{}], widgetsBundleIds [{}]", tenantId, widgetsBundleIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(widgetsBundleIds, ids -> "Incorrect widgetsBundleIds " + ids); - return widgetsBundleDao.findSystemWidgetBundlesByIdsAsync(tenantId.getId(), toUUIDs(widgetsBundleIds)); - } - - @Override - public ListenableFuture> findAllTenantWidgetsBundlesByIdsAsync(TenantId tenantId, List widgetsBundleIds) { - log.trace("Executing findAllTenantWidgetsBundlesByIdsAsync, tenantId [{}], widgetsBundleIds [{}]", tenantId, widgetsBundleIds); - validateId(tenantId, id -> INCORRECT_TENANT_ID + id); - validateIds(widgetsBundleIds, ids -> "Incorrect widgetsBundleIds " + ids); - return widgetsBundleDao.findAllTenantWidgetBundlesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(widgetsBundleIds)); + public List findSystemOrTenantWidgetsBundlesByIds(TenantId tenantId, List widgetsBundleIds) { + log.trace("Executing findSystemOrTenantWidgetsBundlesByIds, tenantId [{}], widgetsBundleIds [{}]", tenantId, widgetsBundleIds); + return widgetsBundleDao.findSystemOrTenantWidgetBundlesByIds(tenantId.getId(), toUUIDs(widgetsBundleIds)); } private WidgetTypeDetails updateSystemWidget(JsonNode widgetTypeJson) {