diff --git a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java index f425bde86c..1cb794c2ec 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -140,6 +140,9 @@ public class ControllerConstants { protected static final String RESOURCE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the resource title."; protected static final String RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, resourceType, tenantId"; + protected static final String RESOURCE_TYPE_PROPERTY_ALLOWABLE_VALUES = "LWM2M_MODEL, JKS, PKCS_12, JS_MODULE"; + protected static final String RESOURCE_TYPE = "A string value representing the resource type."; + protected static final String LWM2M_OBJECT_DESCRIPTION = "LwM2M Object is a object that includes information about the LwM2M model which can be used in transport configuration for the LwM2M device profile. "; protected static final String LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name"; diff --git a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java index d94dc31fa1..316599a092 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java @@ -31,6 +31,8 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.ResourceType; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResourceInfo; import org.thingsboard.server.common.data.exception.ThingsboardException; @@ -57,6 +59,8 @@ import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_ID_ import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_INFO_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_TEXT_SEARCH_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_TYPE; +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_TYPE_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; @@ -153,6 +157,8 @@ public class TbResourceController extends BaseController { @RequestParam int pageSize, @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, + @ApiParam(value = RESOURCE_TYPE, allowableValues = RESOURCE_TYPE_PROPERTY_ALLOWABLE_VALUES) + @RequestParam(required = false) String resourceType, @ApiParam(value = RESOURCE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES) @@ -161,9 +167,17 @@ public class TbResourceController extends BaseController { @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { - return checkNotNull(resourceService.findTenantResourcesByTenantId(getTenantId(), pageLink)); + if (StringUtils.isNotEmpty(resourceType)){ + return checkNotNull(resourceService.findTenantResourcesByType(getTenantId(), ResourceType.valueOf(resourceType), pageLink)); + } else { + return checkNotNull(resourceService.findTenantResourcesByTenantId(getTenantId(), pageLink)); + } } else { - return checkNotNull(resourceService.findAllTenantResourcesByTenantId(getTenantId(), pageLink)); + if (StringUtils.isNotEmpty(resourceType)){ + return checkNotNull(resourceService.findAllTenantResourcesByType(getTenantId(), ResourceType.valueOf(resourceType), pageLink)); + } else { + return checkNotNull(resourceService.findAllTenantResourcesByTenantId(getTenantId(), pageLink)); + } } } diff --git a/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java b/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java index 5cf051367a..ece58397ab 100644 --- a/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java +++ b/application/src/main/java/org/thingsboard/server/service/resource/DefaultTbResourceService.java @@ -85,6 +85,16 @@ public class DefaultTbResourceService extends AbstractTbEntityService implements return resourceService.findTenantResourcesByTenantId(tenantId, pageLink); } + @Override + public PageData findAllTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink) { + return resourceService.findAllTenantResourcesByType(tenantId, resourceType, pageLink); + } + + @Override + public PageData findTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink) { + return resourceService.findTenantResourcesByType(tenantId, resourceType, pageLink); + } + @Override public List findLwM2mObject(TenantId tenantId, String sortOrder, String sortProperty, String[] objectIds) { log.trace("Executing findByTenantId [{}]", tenantId); diff --git a/application/src/main/java/org/thingsboard/server/service/resource/TbResourceService.java b/application/src/main/java/org/thingsboard/server/service/resource/TbResourceService.java index 024d391482..c3b6506abe 100644 --- a/application/src/main/java/org/thingsboard/server/service/resource/TbResourceService.java +++ b/application/src/main/java/org/thingsboard/server/service/resource/TbResourceService.java @@ -39,6 +39,10 @@ public interface TbResourceService extends SimpleTbEntityService { PageData findTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink); + PageData findAllTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink); + + PageData findTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink); + List findLwM2mObject(TenantId tenantId, String sortOrder, String sortProperty, diff --git a/application/src/test/java/org/thingsboard/server/controller/TbResourceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/TbResourceControllerTest.java index de8f717c0d..dbe0c591e9 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TbResourceControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TbResourceControllerTest.java @@ -47,6 +47,7 @@ public class TbResourceControllerTest extends AbstractControllerTest { private IdComparator idComparator = new IdComparator<>(); private static final String DEFAULT_FILE_NAME = "test.jks"; + private static final String DEFAULT_FILE_NAME_2 = "test2.jks"; private Tenant savedTenant; private User tenantAdmin; @@ -242,6 +243,54 @@ public class TbResourceControllerTest extends AbstractControllerTest { Assert.assertEquals(resources, loadedResources); } + @Test + public void testFindTenantTbResourcesByType() throws Exception { + Mockito.reset(tbClusterService, auditLogService); + + List resources = new ArrayList<>(); + int jksCntEntity = 17; + for (int i = 0; i < jksCntEntity; i++) { + TbResource resource = new TbResource(); + resource.setTitle("JKS Resource" + i); + resource.setResourceType(ResourceType.JKS); + resource.setFileName(i + DEFAULT_FILE_NAME); + resource.setData("Test Data"); + resources.add(new TbResourceInfo(save(resource))); + } + + int lwm2mCntEntity = 19; + for (int i = 0; i < lwm2mCntEntity; i++) { + TbResource resource = new TbResource(); + resource.setTitle("LWM2M Resource" + i); + resource.setResourceType(ResourceType.PKCS_12); + resource.setFileName(i + DEFAULT_FILE_NAME_2); + resource.setData("Test Data"); + save(resource); + } + + List loadedResources = new ArrayList<>(); + PageLink pageLink = new PageLink(5); + PageData pageData; + do { + pageData = doGetTypedWithPageLink("/api/resource?resourceType=" + ResourceType.JKS.name() + "&", + new TypeReference<>() { + }, pageLink); + loadedResources.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageLink.nextPageLink(); + } + } while (pageData.hasNext()); + + testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new TbResource(), new TbResource(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.ADDED, jksCntEntity + lwm2mCntEntity); + + Collections.sort(resources, idComparator); + Collections.sort(loadedResources, idComparator); + + Assert.assertEquals(resources, loadedResources); + } + @Test public void testFindSystemTbResources() throws Exception { loginSysAdmin(); @@ -300,6 +349,76 @@ public class TbResourceControllerTest extends AbstractControllerTest { Assert.assertTrue(loadedResources.isEmpty()); } + @Test + public void testFindSystemTbResourcesByType() throws Exception { + loginSysAdmin(); + + List resources = new ArrayList<>(); + int jksCntEntity = 17; + for (int i = 0; i < jksCntEntity; i++) { + TbResource resource = new TbResource(); + resource.setTitle("JKS Resource" + i); + resource.setResourceType(ResourceType.JKS); + resource.setFileName(i + DEFAULT_FILE_NAME); + resource.setData("Test Data"); + resources.add(new TbResourceInfo(save(resource))); + } + + int lwm2mCntEntity = 19; + for (int i = 0; i < lwm2mCntEntity; i++) { + TbResource resource = new TbResource(); + resource.setTitle("LWM2M Resource" + i); + resource.setResourceType(ResourceType.PKCS_12); + resource.setFileName(i + DEFAULT_FILE_NAME_2); + resource.setData("Test Data"); + save(resource); + } + + List loadedResources = new ArrayList<>(); + PageLink pageLink = new PageLink(30); + PageData pageData; + do { + pageData = doGetTypedWithPageLink("/api/resource?resourceType=" + ResourceType.JKS + "&", + new TypeReference<>() { + }, pageLink); + loadedResources.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageLink.nextPageLink(); + } + } while (pageData.hasNext()); + + Collections.sort(resources, idComparator); + Collections.sort(loadedResources, idComparator); + + Assert.assertEquals(resources, loadedResources); + + Mockito.reset(tbClusterService, auditLogService); + + int cntEntity = resources.size(); + for (TbResourceInfo resource : resources) { + doDelete("/api/resource/" + resource.getId().getId().toString()) + .andExpect(status().isOk()); + } + + testNotifyManyEntityManyTimeMsgToEdgeServiceNeverAdditionalInfoAny(new TbResource(), new TbResource(), + resources.get(0).getTenantId(), null, null, SYS_ADMIN_EMAIL, + ActionType.DELETED, cntEntity, 1); + + pageLink = new PageLink(27); + loadedResources.clear(); + do { + pageData = doGetTypedWithPageLink("/api/resource?resourceType=" + ResourceType.JKS + "&", + new TypeReference<>() { + }, pageLink); + loadedResources.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageLink.nextPageLink(); + } + } while (pageData.hasNext()); + + Assert.assertTrue(loadedResources.isEmpty()); + } + @Test public void testFindSystemAndTenantTbResources() throws Exception { List systemResources = new ArrayList<>(); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java index 5e05cdddc6..779fbaf275 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java @@ -43,6 +43,10 @@ public interface ResourceService extends EntityDaoService { PageData findTenantResourcesByTenantId(TenantId tenantId, PageLink pageLink); + PageData findAllTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink); + + PageData findTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink); + List findTenantResourcesByResourceTypeAndObjectIds(TenantId tenantId, ResourceType lwm2mModel, String[] objectIds); PageData findTenantResourcesByResourceTypeAndPageLink(TenantId tenantId, ResourceType lwm2mModel, PageLink pageLink); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ResourceType.java b/common/data/src/main/java/org/thingsboard/server/common/data/ResourceType.java index 31c87ecfde..a9c34a3903 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ResourceType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ResourceType.java @@ -16,5 +16,5 @@ package org.thingsboard.server.common.data; public enum ResourceType { - LWM2M_MODEL, JKS, PKCS_12 + LWM2M_MODEL, JKS, PKCS_12, JS_MODULE } diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java index f5ba4abf2c..3bc02f0a5a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java @@ -116,6 +116,20 @@ public class BaseResourceService implements ResourceService { return resourceInfoDao.findTenantResourcesByTenantId(tenantId.getId(), pageLink); } + @Override + public PageData findAllTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink) { + log.trace("Executing findAllTenantResourcesByType [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + return resourceInfoDao.findAllTenantResourcesByType(tenantId.getId(), resourceType.name(), pageLink); + } + + @Override + public PageData findTenantResourcesByType(TenantId tenantId, ResourceType resourceType, PageLink pageLink) { + log.trace("Executing findTenantResourcesByType [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + return resourceInfoDao.findTenantResourcesByType(tenantId.getId(), resourceType.name(), pageLink); + } + @Override public List findTenantResourcesByResourceTypeAndObjectIds(TenantId tenantId, ResourceType resourceType, String[] objectIds) { log.trace("Executing findTenantResourcesByResourceTypeAndObjectIds [{}][{}][{}]", tenantId, resourceType, objectIds); diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/TbResourceInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/resource/TbResourceInfoDao.java index 6a726cd6ec..4b383556b7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/TbResourceInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/TbResourceInfoDao.java @@ -28,4 +28,8 @@ public interface TbResourceInfoDao extends Dao { PageData findTenantResourcesByTenantId(UUID tenantId, PageLink pageLink); + PageData findAllTenantResourcesByType(UUID tenantId, String resourceType, PageLink pageLink); + + PageData findTenantResourcesByType(UUID tenantId, String resourceType, PageLink pageLink); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceInfoDao.java index 837ab63fb3..041f774ab9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceInfoDao.java @@ -68,4 +68,25 @@ public class JpaTbResourceInfoDao extends JpaAbstractSearchTextDao findAllTenantResourcesByType(UUID tenantId, String resourceType, PageLink pageLink) { + return DaoUtil.toPageData(resourceInfoRepository + .findAllTenantResourcesByType( + tenantId, + TenantId.NULL_UUID, + resourceType, + Objects.toString(pageLink.getTextSearch(), ""), + DaoUtil.toPageable(pageLink))); + } + + @Override + public PageData findTenantResourcesByType(UUID tenantId, String resourceType, PageLink pageLink) { + return DaoUtil.toPageData(resourceInfoRepository + .findTenantResourcesByType( + tenantId, + resourceType, + Objects.toString(pageLink.getTextSearch(), ""), + DaoUtil.toPageable(pageLink))); + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceInfoRepository.java index dde66910df..b6a37f5578 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceInfoRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceInfoRepository.java @@ -46,4 +46,29 @@ public interface TbResourceInfoRepository extends JpaRepository findTenantResourcesByTenantId(@Param("tenantId") UUID tenantId, @Param("searchText") String searchText, Pageable pageable); + + @Query("SELECT tr FROM TbResourceInfoEntity tr WHERE " + + "LOWER(tr.title) LIKE LOWER(CONCAT('%', :searchText, '%'))" + + "AND (tr.tenantId = :tenantId " + + "OR (tr.tenantId = :systemAdminId " + + "AND NOT EXISTS " + + "(SELECT sr FROM TbResourceEntity sr " + + "WHERE sr.tenantId = :tenantId " + + "AND tr.resourceType = sr.resourceType " + + "AND tr.resourceKey = sr.resourceKey)))" + + "AND tr.resourceType = :resourceType") + Page findAllTenantResourcesByType(@Param("tenantId") UUID tenantId, + @Param("systemAdminId") UUID sysadminId, + @Param("resourceType") String resourceType, + @Param("searchText") String searchText, + Pageable pageable); + + @Query("SELECT ri FROM TbResourceInfoEntity ri WHERE " + + "ri.tenantId = :tenantId " + + "AND ri.resourceType = :resourceType " + + "AND LOWER(ri.title) LIKE LOWER(CONCAT('%', :searchText, '%'))") + Page findTenantResourcesByType(@Param("tenantId") UUID tenantId, + @Param("resourceType") String resourceType, + @Param("searchText") String searchText, + Pageable pageable); }