diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 06c8536187..eb9eed07e8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -488,7 +488,7 @@ public class AssetController extends BaseController { } } - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeAssets( @@ -507,11 +507,25 @@ public class AssetController extends BaseController { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); + PageData nonFilteredResult; if (type != null && type.trim().length() > 0) { - return checkNotNull(assetService.findAssetsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink)); + nonFilteredResult = assetService.findAssetsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink); } else { - return checkNotNull(assetService.findAssetsByTenantIdAndEdgeId(tenantId, edgeId, pageLink)); + nonFilteredResult = assetService.findAssetsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); } + List filteredAssets = nonFilteredResult.getData().stream().filter(asset -> { + try { + accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset); + return true; + } catch (ThingsboardException e) { + return false; + } + }).collect(Collectors.toList()); + PageData filteredResult = new PageData<>(filteredAssets, + nonFilteredResult.getTotalPages(), + nonFilteredResult.getTotalElements(), + nonFilteredResult.hasNext()); + return checkNotNull(filteredResult); } catch (Exception e) { throw handleException(e); } 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 28eb7b9a76..39ec2c2bba 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -49,6 +49,7 @@ import org.thingsboard.server.service.security.permission.Resource; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; @RestController @TbCoreComponent @@ -555,7 +556,7 @@ public class DashboardController extends BaseController { } } - @PreAuthorize("hasAuthority('TENANT_ADMIN')") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeDashboards( @@ -573,7 +574,20 @@ public class DashboardController extends BaseController { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); - return checkNotNull(dashboardService.findDashboardsByTenantIdAndEdgeId(tenantId, edgeId, pageLink)); + 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()); + PageData filteredResult = new PageData<>(filteredDashboards, + nonFilteredResult.getTotalPages(), + nonFilteredResult.getTotalElements(), + nonFilteredResult.hasNext()); + return checkNotNull(filteredResult); } catch (Exception e) { throw handleException(e); } diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 7f54c464f0..615e38a8c8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -711,13 +711,14 @@ public class DeviceController extends BaseController { } } - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeDevices( @PathVariable(EDGE_ID) String strEdgeId, @RequestParam int pageSize, @RequestParam int page, + @RequestParam(required = false) String type, @RequestParam(required = false) String textSearch, @RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortOrder, @@ -729,7 +730,25 @@ public class DeviceController extends BaseController { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); - return checkNotNull(deviceService.findDevicesByTenantIdAndEdgeId(tenantId, edgeId, pageLink)); + PageData nonFilteredResult; + if (type != null && type.trim().length() > 0) { + nonFilteredResult = deviceService.findDevicesByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink); + } else { + nonFilteredResult = deviceService.findDevicesByTenantIdAndEdgeId(tenantId, edgeId, pageLink); + } + List filteredDevices = nonFilteredResult.getData().stream().filter(device -> { + try { + accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device); + return true; + } catch (ThingsboardException e) { + return false; + } + }).collect(Collectors.toList()); + PageData filteredResult = new PageData<>(filteredDevices, + nonFilteredResult.getTotalPages(), + nonFilteredResult.getTotalElements(), + nonFilteredResult.hasNext()); + return checkNotNull(filteredResult); } catch (Exception e) { throw handleException(e); } 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 93b72dd01d..aee1bd7bea 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityViewInfo; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEventActionType; @@ -258,7 +259,7 @@ public class EntityViewController extends BaseController { private ListenableFuture> copyLatestFromEntityToEntityView(EntityView entityView, SecurityUser user) { EntityViewId entityId = entityView.getId(); List keys = entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null ? - entityView.getKeys().getTimeseries() : Collections.emptyList(); + entityView.getKeys().getTimeseries() : Collections.emptyList(); long startTs = entityView.getStartTimeMs(); long endTs = entityView.getEndTimeMs() == 0 ? Long.MAX_VALUE : entityView.getEndTimeMs(); ListenableFuture> keysFuture; @@ -673,7 +674,7 @@ public class EntityViewController extends BaseController { } } - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeEntityViews( @@ -692,11 +693,25 @@ public class EntityViewController extends BaseController { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); + PageData nonFilteredResult; if (type != null && type.trim().length() > 0) { - return checkNotNull(entityViewService.findEntityViewsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink)); + nonFilteredResult = entityViewService.findEntityViewsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink); } else { - return checkNotNull(entityViewService.findEntityViewsByTenantIdAndEdgeId(tenantId, edgeId, pageLink)); + 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()); + PageData filteredResult = new PageData<>(filteredEntityViews, + nonFilteredResult.getTotalPages(), + nonFilteredResult.getTotalElements(), + nonFilteredResult.hasNext()); + return checkNotNull(filteredResult); } catch (Exception e) { throw handleException(e); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java index bed9dc476a..cbb5be0bec 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java @@ -94,4 +94,6 @@ public interface DeviceService { Device unassignDeviceFromEdge(TenantId tenantId, DeviceId deviceId, EdgeId edgeId); PageData findDevicesByTenantIdAndEdgeId(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink); + + PageData findDevicesByTenantIdAndEdgeIdAndType(TenantId tenantId, EdgeId edgeId, String type, TimePageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java index 701f54390f..5a443119e6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java @@ -227,4 +227,15 @@ public interface DeviceDao extends Dao, TenantEntityDao { * @return the list of device objects */ PageData findDevicesByTenantIdAndEdgeId(UUID tenantId, UUID edgeId, TimePageLink pageLink); + + /** + * Find devices by tenantId, edgeId, type and page link. + * + * @param tenantId the tenantId + * @param edgeId the edgeId + * @param type the type + * @param pageLink the page link + * @return the list of device objects + */ + PageData findDevicesByTenantIdAndEdgeIdAndType(UUID tenantId, UUID edgeId, String type, TimePageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index a453462da7..3d8b28da70 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.device.DeviceSearchQuery; import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration; @@ -571,6 +572,16 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe return deviceDao.findDevicesByTenantIdAndEdgeId(tenantId.getId(), edgeId.getId(), pageLink); } + @Override + public PageData findDevicesByTenantIdAndEdgeIdAndType(TenantId tenantId, EdgeId edgeId, String type, TimePageLink pageLink) { + log.trace("Executing findDevicesByTenantIdAndEdgeIdAndType, tenantId [{}], edgeId [{}], type [{}] pageLink [{}]", tenantId, edgeId, type, pageLink); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + validateId(edgeId, INCORRECT_EDGE_ID + edgeId); + validateString(type, "Incorrect type " + type); + validatePageLink(pageLink); + return deviceDao.findDevicesByTenantIdAndEdgeIdAndType(tenantId.getId(), edgeId.getId(), type, pageLink); + } + private DataValidator deviceValidator = new DataValidator() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java index 85cbaac320..b6aaeb4d18 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java @@ -178,5 +178,16 @@ public interface DeviceRepository extends PagingAndSortingRepository findByTenantIdAndEdgeIdAndType(@Param("tenantId") UUID tenantId, + @Param("edgeId") UUID edgeId, + @Param("type") String type, + @Param("searchText") String searchText, + Pageable pageable); + Long countByTenantId(UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index fce992e4c2..0d508b6927 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -248,4 +248,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao Objects.toString(pageLink.getTextSearch(), ""), DaoUtil.toPageable(pageLink))); } + + @Override + public PageData findDevicesByTenantIdAndEdgeIdAndType(UUID tenantId, UUID edgeId, String type, TimePageLink pageLink) { + log.debug("Try to find devices by tenantId [{}], edgeId [{}], type [{}] and pageLink [{}]", tenantId, edgeId, type, pageLink); + return DaoUtil.toPageData(deviceRepository + .findByTenantIdAndEdgeIdAndType( + tenantId, + edgeId, + type, + Objects.toString(pageLink.getTextSearch(), ""), + DaoUtil.toPageable(pageLink))); + } } diff --git a/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts index 4b2a73602d..c715fc945c 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts @@ -121,7 +121,11 @@ export class AssetsTableConfigResolver implements Resolve { if (authUser.authority === Authority.CUSTOMER_USER) { - this.config.componentsData.assetScope = 'customer_user'; + if (route.data.assetsType === 'edge') { + this.config.componentsData.assetScope = 'edge_customer_user'; + } else { + this.config.componentsData.assetScope = 'customer_user'; + } this.customerId = authUser.customerId; } }), @@ -179,7 +183,7 @@ export class AssetsTableConfigResolver implements Resolve this.assetService.getTenantAssetInfos(pageLink, this.config.componentsData.assetType); this.config.deleteEntity = id => this.assetService.deleteAsset(id.id); - } else if (assetScope === 'edge') { + } else if (assetScope === 'edge' || assetScope === 'edge_customer_user') { this.config.entitiesFetchFunction = pageLink => this.assetService.getEdgeAssets(this.config.componentsData.edgeId, pageLink, this.config.componentsData.assetType); } else { diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts index 8aac1420f2..ccef49ec98 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts @@ -116,7 +116,11 @@ export class DashboardsTableConfigResolver implements Resolve { if (authUser.authority === Authority.CUSTOMER_USER) { - this.config.componentsData.dashboardScope = 'customer_user'; + if (route.data.dashboardsType === 'edge') { + this.config.componentsData.dashboardScope = 'edge_customer_user'; + } else { + this.config.componentsData.dashboardScope = 'customer_user'; + } this.config.componentsData.customerId = authUser.customerId; } }), @@ -176,7 +180,7 @@ export class DashboardsTableConfigResolver implements Resolve this.dashboardService.getTenantDashboards(pageLink); this.config.deleteEntity = id => this.dashboardService.deleteDashboard(id.id); - } else if (dashboardScope === 'edge') { + } else if (dashboardScope === 'edge' || dashboardScope === 'edge_customer_user') { this.config.entitiesFetchFunction = pageLink => this.dashboardService.getEdgeDashboards(this.config.componentsData.edgeId, pageLink, this.config.componentsData.dashboardsType); } else { diff --git a/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts index 6abd204962..f3471a0c87 100644 --- a/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts @@ -131,7 +131,11 @@ export class DevicesTableConfigResolver implements Resolve { if (authUser.authority === Authority.CUSTOMER_USER) { - this.config.componentsData.deviceScope = 'customer_user'; + if (route.data.devicesType === 'edge') { + this.config.componentsData.deviceScope = 'edge_customer_user'; + } else { + this.config.componentsData.deviceScope = 'customer_user'; + } this.customerId = authUser.customerId; } }), @@ -197,7 +201,7 @@ export class DevicesTableConfigResolver implements Resolve this.deviceService.deleteDevice(id.id); - } else if (deviceScope === 'edge') { + } else if (deviceScope === 'edge' || deviceScope === 'edge_customer_user') { this.config.entitiesFetchFunction = pageLink => this.deviceService.getEdgeDevices(this.config.componentsData.edgeId, pageLink, this.config.componentsData.edgeType); } else { @@ -267,7 +271,7 @@ export class DevicesTableConfigResolver implements Resolve + [fxShow]="!isEdit && (edgeScope === 'tenant' || edgeScope === 'customer_user')"> {{'edge.manage-edge-assets' | translate }}