From 72ae6eb70848646e6afb3c5994afb7c824eba51f Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 16 Nov 2023 15:13:00 +0200 Subject: [PATCH] Version control support for resources --- .../main/data/upgrade/3.6.1/schema_update.sql | 1 + .../server/controller/ImageController.java | 10 +-- .../controller/TbResourceController.java | 25 ++++++ .../DefaultExportableEntitiesService.java | 10 +++ .../exporting/ExportableEntitiesService.java | 2 + .../exporting/impl/ResourceExportService.java | 36 ++++++++ .../importing/impl/ResourceImportService.java | 83 +++++++++++++++++++ .../impl/WidgetTypeImportService.java | 4 - .../DefaultEntitiesVersionControlService.java | 6 +- .../server/dao/resource/ResourceService.java | 2 +- .../server/common/data/TbResource.java | 3 - .../server/common/data/TbResourceInfo.java | 28 +++++-- .../server/common/data/sync/JsonTbEntity.java | 4 +- .../server/dao/ExportableEntityDao.java | 6 +- .../dao/model/sql/TbResourceEntity.java | 6 ++ .../dao/model/sql/TbResourceInfoEntity.java | 6 ++ .../server/dao/resource/BaseImageService.java | 2 +- .../dao/resource/BaseResourceService.java | 8 +- .../server/dao/resource/TbResourceDao.java | 3 +- .../dao/sql/resource/JpaTbResourceDao.java | 21 +++++ .../resource/TbResourceInfoRepository.java | 4 +- .../sql/resource/TbResourceRepository.java | 9 +- .../dao/sql/widget/JpaWidgetTypeDao.java | 8 +- .../dao/sql/widget/WidgetTypeRepository.java | 5 +- .../main/resources/sql/schema-entities.sql | 1 + 25 files changed, 259 insertions(+), 34 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/ResourceExportService.java create mode 100644 application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/ResourceImportService.java diff --git a/application/src/main/data/upgrade/3.6.1/schema_update.sql b/application/src/main/data/upgrade/3.6.1/schema_update.sql index c19ea2e4e8..27c7adf523 100644 --- a/application/src/main/data/upgrade/3.6.1/schema_update.sql +++ b/application/src/main/data/upgrade/3.6.1/schema_update.sql @@ -30,5 +30,6 @@ $$; ALTER TABLE resource ADD COLUMN IF NOT EXISTS descriptor varchar, ADD COLUMN IF NOT EXISTS preview bytea; +ALTER TABLE resource ADD COLUMN IF NOT EXISTS external_id uuid -- RESOURCES UPDATE END diff --git a/application/src/main/java/org/thingsboard/server/controller/ImageController.java b/application/src/main/java/org/thingsboard/server/controller/ImageController.java index add38ee272..98e7a3a4e8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ImageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ImageController.java @@ -35,7 +35,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ImageDescriptor; import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.TbResource; @@ -88,7 +87,7 @@ public class ImageController extends BaseController { image.setResourceType(ResourceType.IMAGE); ImageDescriptor descriptor = new ImageDescriptor(); descriptor.setMediaType(file.getContentType()); - image.setDescriptor(JacksonUtil.valueToTree(descriptor)); + image.setDescriptorValue(descriptor); image.setData(file.getBytes()); return tbImageService.save(image, user); } @@ -99,11 +98,12 @@ public class ImageController extends BaseController { @PathVariable String key, @RequestPart MultipartFile file) throws Exception { TbResourceInfo imageInfo = checkImageInfo(type, key, Operation.WRITE); - ImageDescriptor descriptor = imageInfo.getDescriptor(ImageDescriptor.class); - TbResource image = new TbResource(imageInfo); image.setData(file.getBytes()); - descriptor.setMediaType(file.getContentType()); + image.updateDescriptor(ImageDescriptor.class, descriptor -> { + descriptor.setMediaType(file.getContentType()); + return descriptor; + }); return tbImageService.save(image, getCurrentUser()); } 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 b8abaab0ae..c5445e4465 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java @@ -53,6 +53,7 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.Collections; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -226,6 +227,30 @@ public class TbResourceController extends BaseController { } } + @ApiOperation(value = "Get All Resource Infos (getAllResources)", + notes = "Returns a page of Resource Info objects owned by tenant. " + + PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, + produces = "application/json") + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @GetMapping(value = "/resource/tenant") + public PageData getTenantResources(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @RequestParam int page, + @ApiParam(value = RESOURCE_TEXT_SEARCH_DESCRIPTION) + @RequestParam(required = false) String textSearch, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES) + @RequestParam(required = false) String sortProperty, + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @RequestParam(required = false) String sortOrder) throws ThingsboardException { + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); + TbResourceInfoFilter filter = TbResourceInfoFilter.builder() + .tenantId(getTenantId()) + .resourceTypes(EnumSet.allOf(ResourceType.class)) + .build(); + return checkNotNull(resourceService.findTenantResourcesByTenantId(filter, pageLink)); + } + @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjectsPage)", notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/DefaultExportableEntitiesService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/DefaultExportableEntitiesService.java index 3358e5182f..d112075a51 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/DefaultExportableEntitiesService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/DefaultExportableEntitiesService.java @@ -118,6 +118,16 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi } } + @Override + public PageData findEntitiesIdsByTenantId(TenantId tenantId, EntityType entityType, PageLink pageLink) { + ExportableEntityDao dao = getExportableEntityDao(entityType); + if (dao != null) { + return dao.findIdsByTenantId(tenantId.getId(), pageLink); + } else { + return new PageData<>(); + } + } + @Override public I getExternalIdByInternal(I internalId) { ExportableEntityDao dao = getExportableEntityDao(internalId.getEntityType()); diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/ExportableEntitiesService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/ExportableEntitiesService.java index c5c26c4476..eee102961d 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/ExportableEntitiesService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/ExportableEntitiesService.java @@ -35,6 +35,8 @@ public interface ExportableEntitiesService { , I extends EntityId> PageData findEntitiesByTenantId(TenantId tenantId, EntityType entityType, PageLink pageLink); + PageData findEntitiesIdsByTenantId(TenantId tenantId, EntityType entityType, PageLink pageLink); + I getExternalIdByInternal(I internalId); void removeById(TenantId tenantId, I id); diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/ResourceExportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/ResourceExportService.java new file mode 100644 index 0000000000..45e21f5fb4 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/ResourceExportService.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.sync.ie.exporting.impl; + +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.TbResource; +import org.thingsboard.server.common.data.id.TbResourceId; +import org.thingsboard.server.common.data.sync.ie.EntityExportData; +import org.thingsboard.server.queue.util.TbCoreComponent; + +import java.util.Set; + +@Service +@TbCoreComponent +public class ResourceExportService extends BaseEntityExportService> { + + @Override + public Set getSupportedEntityTypes() { + return Set.of(EntityType.TB_RESOURCE); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/ResourceImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/ResourceImportService.java new file mode 100644 index 0000000000..bc7db18e80 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/ResourceImportService.java @@ -0,0 +1,83 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.sync.ie.importing.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.TbResource; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TbResourceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.sync.ie.EntityExportData; +import org.thingsboard.server.dao.resource.ResourceService; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx; + +@Service +@TbCoreComponent +@RequiredArgsConstructor +public class ResourceImportService extends BaseEntityImportService> { + + private final ResourceService resourceService; + + @Override + protected void setOwner(TenantId tenantId, TbResource resource, IdProvider idProvider) { + resource.setTenantId(tenantId); + } + + @Override + protected TbResource prepare(EntitiesImportCtx ctx, TbResource resource, TbResource oldResource, EntityExportData exportData, IdProvider idProvider) { + return resource; + } + + @Override + protected TbResource findExistingEntity(EntitiesImportCtx ctx, TbResource resource, IdProvider idProvider) { + TbResource existingResource = super.findExistingEntity(ctx, resource, idProvider); + if (existingResource == null && ctx.isFindExistingByName()) { + existingResource = resourceService.findResourceByTenantIdAndKey(ctx.getTenantId(), resource.getResourceType(), resource.getResourceKey()); + } + return existingResource; + } + + @Override + protected boolean compare(EntitiesImportCtx ctx, EntityExportData exportData, TbResource prepared, TbResource existing) { + return true; + } + + @Override + protected TbResource deepCopy(TbResource resource) { + return new TbResource(resource); + } + + @Override + protected TbResource saveOrUpdate(EntitiesImportCtx ctx, TbResource resource, EntityExportData exportData, IdProvider idProvider) { + return resourceService.saveResource(resource); + } + + @Override + protected void onEntitySaved(User user, TbResource savedResource, TbResource oldResource) throws ThingsboardException { + super.onEntitySaved(user, savedResource, oldResource); + clusterService.onResourceChange(savedResource, null); + } + + @Override + public EntityType getEntityType() { + return EntityType.TB_RESOURCE; + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/WidgetTypeImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/WidgetTypeImportService.java index 88ebbbcee3..78cd9a66f6 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/WidgetTypeImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/WidgetTypeImportService.java @@ -20,13 +20,9 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; -import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.sync.ie.WidgetTypeExportData; -import org.thingsboard.server.common.data.sync.ie.WidgetsBundleExportData; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; -import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.widget.WidgetTypeService; -import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java index 89d5153a81..f98a2ad780 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java @@ -208,10 +208,10 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont } if (config.isAllEntities()) { - DaoUtil.processInBatches(pageLink -> exportableEntitiesService.findEntitiesByTenantId(ctx.getTenantId(), entityType, pageLink) - , 100, entity -> { + DaoUtil.processInBatches(pageLink -> exportableEntitiesService.findEntitiesIdsByTenantId(ctx.getTenantId(), entityType, pageLink), + 100, entityId -> { try { - ctx.add(saveEntityData(ctx, entity.getId())); + ctx.add(saveEntityData(ctx, entityId)); } catch (Exception e) { throw new RuntimeException(e); } 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 7240b1b742..21b83d17bd 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 @@ -34,7 +34,7 @@ public interface ResourceService extends EntityDaoService { TbResource saveResource(TbResource resource, boolean doValidate); - TbResource findResourceByTenantIdAndKey(TenantId tenantId, ResourceType resourceType, String resourceId); + TbResource findResourceByTenantIdAndKey(TenantId tenantId, ResourceType resourceType, String resourceKey); TbResource findResourceById(TenantId tenantId, TbResourceId resourceId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java b/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java index c76d2b5c2d..2324eae1a7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java @@ -16,7 +16,6 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonSetter; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -34,10 +33,8 @@ public class TbResource extends TbResourceInfo { private static final long serialVersionUID = 7379609705527272306L; - @JsonIgnore private byte[] data; - @JsonIgnore private byte[] preview; public TbResource() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java index 31ef6b8ea1..11e21c6451 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -30,11 +29,13 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; +import java.util.function.UnaryOperator; + @ApiModel @Slf4j @Data @EqualsAndHashCode(callSuper = true) -public class TbResourceInfo extends BaseData implements HasName, HasTenantId { +public class TbResourceInfo extends BaseData implements HasName, HasTenantId, ExportableEntity { private static final long serialVersionUID = 7282664529021651736L; @@ -52,15 +53,17 @@ public class TbResourceInfo extends BaseData implements HasName, H private String resourceKey; @ApiModelProperty(position = 7, value = "Resource search text.", example = "19_1.0:binaryappdatacontainer", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String searchText; + @ApiModelProperty(position = 8, value = "Resource etag.", example = "33a64df551425fcc55e4d42a148795d9f25f89d4", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String etag; @NoXss @Length(fieldName = "file name") @ApiModelProperty(position = 9, value = "Resource file name.", example = "19.xml", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String fileName; - @JsonProperty(access = JsonProperty.Access.READ_ONLY) private JsonNode descriptor; + private TbResourceId externalId; + public TbResourceInfo() { super(); } @@ -78,13 +81,14 @@ public class TbResourceInfo extends BaseData implements HasName, H this.searchText = resourceInfo.searchText; this.etag = resourceInfo.etag; this.fileName = resourceInfo.fileName; - this.descriptor = resourceInfo.descriptor; + this.descriptor = resourceInfo.descriptor != null ? resourceInfo.descriptor.deepCopy() : null; + this.externalId = resourceInfo.externalId; } @ApiModelProperty(position = 1, value = "JSON object with the Resource Id. " + "Specify this field to update the Resource. " + "Referencing non-existing Resource Id will cause error. " + - "Omit this field to create new Resource." ) + "Omit this field to create new Resource.") @Override public TbResourceId getId() { return super.getId(); @@ -97,7 +101,7 @@ public class TbResourceInfo extends BaseData implements HasName, H } @Override - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return title; } @@ -107,9 +111,19 @@ public class TbResourceInfo extends BaseData implements HasName, H return searchText != null ? searchText : title; } - @JsonIgnore public T getDescriptor(Class type) throws JsonProcessingException { return descriptor != null ? mapper.treeToValue(descriptor, type) : null; } + public void updateDescriptor(Class type, UnaryOperator updater) throws JsonProcessingException { + T descriptor = getDescriptor(type); + descriptor = updater.apply(descriptor); + setDescriptorValue(descriptor); + } + + @JsonIgnore + public void setDescriptorValue(Object value) { + this.descriptor = value != null ? mapper.valueToTree(value) : null; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java index 92c6a332df..10f20cc973 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/JsonTbEntity.java @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.notification.rule.NotificationRule; @@ -56,7 +57,8 @@ import java.lang.annotation.Target; @Type(name = "WIDGET_TYPE", value = WidgetTypeDetails.class), @Type(name = "NOTIFICATION_TEMPLATE", value = NotificationTemplate.class), @Type(name = "NOTIFICATION_TARGET", value = NotificationTarget.class), - @Type(name = "NOTIFICATION_RULE", value = NotificationRule.class) + @Type(name = "NOTIFICATION_RULE", value = NotificationRule.class), + @Type(name = "TB_RESOURCE", value = TbResource.class) }) @JsonIgnoreProperties(value = {"tenantId", "createdTime"}, ignoreUnknown = true) public @interface JsonTbEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java b/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java index 169d7c3b88..5ac75f94f7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.page.PageLink; import java.util.UUID; -public interface ExportableEntityDao> extends Dao { +public interface ExportableEntityDao> extends Dao { T findByTenantIdAndExternalId(UUID tenantId, UUID externalId); @@ -30,6 +30,10 @@ public interface ExportableEntityDao findByTenantId(UUID tenantId, PageLink pageLink); + default PageData findIdsByTenantId(UUID tenantId, PageLink pageLink) { + return findByTenantId(tenantId, pageLink).mapData(ExportableEntity::getId); + } + I getExternalIdByInternal(I internalId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java index 41c5ebc920..ff63994259 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java @@ -32,6 +32,7 @@ import javax.persistence.Entity; import javax.persistence.Table; import java.util.UUID; +import static org.thingsboard.server.dao.model.ModelConstants.EXTERNAL_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_DATA_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_DESCRIPTOR_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_ETAG_COLUMN; @@ -82,6 +83,9 @@ public class TbResourceEntity extends BaseSqlEntity { @Column(name = RESOURCE_PREVIEW_COLUMN) private byte[] preview; + @Column(name = EXTERNAL_ID_PROPERTY) + private UUID externalId; + public TbResourceEntity() { } @@ -102,6 +106,7 @@ public class TbResourceEntity extends BaseSqlEntity { this.etag = resource.getEtag(); this.descriptor = resource.getDescriptor(); this.preview = resource.getPreview(); + this.externalId = getUuid(resource.getExternalId()); } @Override @@ -118,6 +123,7 @@ public class TbResourceEntity extends BaseSqlEntity { resource.setEtag(etag); resource.setDescriptor(descriptor); resource.setPreview(preview); + resource.setExternalId(getEntityId(externalId, TbResourceId::new)); return resource; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java index 9ab5024b32..1244e25d4c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java @@ -33,6 +33,7 @@ import javax.persistence.Entity; import javax.persistence.Table; import java.util.UUID; +import static org.thingsboard.server.dao.model.ModelConstants.EXTERNAL_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_DESCRIPTOR_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_ETAG_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_FILE_NAME_COLUMN; @@ -75,6 +76,9 @@ public class TbResourceInfoEntity extends BaseSqlEntity implemen @Column(name = RESOURCE_DESCRIPTOR_COLUMN) private JsonNode descriptor; + @Column(name = EXTERNAL_ID_PROPERTY) + private UUID externalId; + public TbResourceInfoEntity() { } @@ -91,6 +95,7 @@ public class TbResourceInfoEntity extends BaseSqlEntity implemen this.hashCode = resource.getEtag(); this.fileName = resource.getFileName(); this.descriptor = resource.getDescriptor(); + this.externalId = getUuid(resource.getExternalId()); } @Override @@ -105,6 +110,7 @@ public class TbResourceInfoEntity extends BaseSqlEntity implemen resource.setEtag(hashCode); resource.setFileName(fileName); resource.setDescriptor(descriptor); + resource.setExternalId(getEntityId(externalId, TbResourceId::new)); return resource; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java index 778192b49c..857296b9b5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java @@ -59,7 +59,7 @@ public class BaseImageService extends BaseResourceService implements ImageServic Pair result = processImage(image.getData(), descriptor); descriptor = result.getLeft(); image.setEtag(descriptor.getEtag()); - image.setDescriptor(JacksonUtil.valueToTree(descriptor)); + image.setDescriptorValue(descriptor); image.setPreview(result.getRight()); return new TbResourceInfo(doSaveResource(image)); 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 bb881e5dcd..9be95db9e7 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 @@ -96,8 +96,7 @@ public class BaseResourceService extends AbstractCachedEntityService, TenantEntityWithDataDao { +public interface TbResourceDao extends Dao, TenantEntityWithDataDao, ExportableEntityDao { TbResource findResourceByTenantIdAndKey(TenantId tenantId, ResourceType resourceType, String resourceId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceDao.java index 28bebf3e4f..370b21a90e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/JpaTbResourceDao.java @@ -109,6 +109,27 @@ public class JpaTbResourceDao extends JpaAbstractDao findByTenantId(UUID tenantId, PageLink pageLink) { + return findAllByTenantId(TenantId.fromUUID(tenantId), pageLink); + } + + @Override + public PageData findIdsByTenantId(UUID tenantId, PageLink pageLink) { + return DaoUtil.pageToPageData(resourceRepository.findIdsByTenantId(tenantId, DaoUtil.toPageable(pageLink)) + .map(TbResourceId::new)); + } + + @Override + public TbResourceId getExternalIdByInternal(TbResourceId internalId) { + return DaoUtil.toEntityId(resourceRepository.getExternalIdByInternal(internalId.getId()), TbResourceId::new); + } + @Override public EntityType getEntityType() { return EntityType.TB_RESOURCE; 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 9c526ae321..0a0f7ff127 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 @@ -59,8 +59,8 @@ public interface TbResourceInfoRepository extends JpaRepository findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(@Param("tenantId") UUID tenantId, - @Param("resourceType") String resourceType, - @Param("resourceKeyStartsWith") String resourceKeyStartsWith); + @Param("resourceType") String resourceType, + @Param("resourceKeyStartsWith") String resourceKeyStartsWith); List findByTenantIdAndHashCodeAndResourceKeyStartingWith(UUID tenantId, String hashCode, String query); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java index 6a47e95ed6..b6d52909ff 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java @@ -20,12 +20,13 @@ 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.dao.ExportableEntityRepository; import org.thingsboard.server.dao.model.sql.TbResourceEntity; import java.util.List; import java.util.UUID; -public interface TbResourceRepository extends JpaRepository { +public interface TbResourceRepository extends JpaRepository , ExportableEntityRepository { TbResourceEntity findByTenantIdAndResourceTypeAndResourceKey(UUID tenantId, String resourceType, String resourceKey); @@ -87,4 +88,10 @@ public interface TbResourceRepository extends JpaRepository findIdsByTenantId(@Param("tenantId") UUID tenantId, Pageable pageable); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java index a821191629..f1878e1de8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java @@ -121,7 +121,7 @@ public class JpaWidgetTypeDao extends JpaAbstractDao findTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List widgetTypes, PageLink pageLink) { + public PageData findTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List widgetTypes, PageLink pageLink) { boolean deprecatedFilterEnabled = !DeprecatedFilter.ALL.equals(deprecatedFilter); boolean deprecatedFilterBool = DeprecatedFilter.DEPRECATED.equals(deprecatedFilter); boolean widgetTypesEmpty = widgetTypes == null || widgetTypes.isEmpty(); @@ -204,6 +204,12 @@ public class JpaWidgetTypeDao extends JpaAbstractDao findIdsByTenantId(UUID tenantId, PageLink pageLink) { + return DaoUtil.pageToPageData(widgetTypeRepository.findIdsByTenantId(tenantId, DaoUtil.toPageable(pageLink)) + .map(WidgetTypeId::new)); + } + @Override public WidgetTypeId getExternalIdByInternal(WidgetTypeId internalId) { return Optional.ofNullable(widgetTypeRepository.getExternalIdById(internalId.getId())) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java index d85f486a05..7536133643 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java @@ -76,7 +76,10 @@ public interface WidgetTypeRepository extends JpaRepository findAllIds(Pageable pageable); + @Query("SELECT id FROM WidgetTypeDetailsEntity WHERE tenantId = :tenantId") + Page findIdsByTenantId(@Param("tenantId") UUID tenantId, Pageable pageable); + } diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 6b30151536..35d1d49cda 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -718,6 +718,7 @@ CREATE TABLE IF NOT EXISTS resource ( etag varchar, descriptor varchar, preview bytea, + external_id uuid, CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_key) );