Browse Source

Implement force delete of the image

pull/9542/head
Andrii Shvaika 3 years ago
parent
commit
b61e6d878c
  1. 11
      application/src/main/java/org/thingsboard/server/controller/ImageController.java
  2. 1
      application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java
  3. 11
      application/src/main/java/org/thingsboard/server/service/resource/DefaultTbImageService.java
  4. 3
      application/src/main/java/org/thingsboard/server/service/resource/TbImageService.java
  5. 3
      common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ImageService.java
  6. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java
  7. 32
      common/data/src/main/java/org/thingsboard/server/common/data/TbImageDeleteResult.java
  8. 29
      dao/src/main/java/org/thingsboard/server/dao/ImageContainerDao.java
  9. 2
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java
  10. 4
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java
  11. 7
      dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java
  12. 4
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java
  13. 69
      dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java
  14. 10
      dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java
  15. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetProfileRepository.java
  16. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java
  17. 13
      dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java
  18. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java
  19. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java
  20. 13
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java
  21. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
  22. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
  23. 13
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java
  24. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java
  25. 3
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java
  26. 4
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java
  27. 23
      dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java

11
application/src/main/java/org/thingsboard/server/controller/ImageController.java

@ -50,14 +50,13 @@ import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.resource.ImageService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.resource.ImageCacheKey;
import org.thingsboard.server.common.data.TbImageDeleteResult;
import org.thingsboard.server.service.resource.TbImageService;
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.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
@ -174,10 +173,12 @@ public class ImageController extends BaseController {
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@DeleteMapping(IMAGE_URL)
public void deleteImage(@PathVariable String type,
@PathVariable String key) throws ThingsboardException {
public ResponseEntity<TbImageDeleteResult> deleteImage(@PathVariable String type,
@PathVariable String key,
@RequestParam(name = "force", required = false) boolean force) throws ThingsboardException {
TbResourceInfo imageInfo = checkImageInfo(type, key, Operation.DELETE);
tbImageService.delete(imageInfo, getCurrentUser());
TbImageDeleteResult result = tbImageService.delete(imageInfo, getCurrentUser(), force);
return (result.isSuccess() ? ResponseEntity.ok() : ResponseEntity.badRequest()).body(result);
}
private ResponseEntity<ByteArrayResource> downloadIfChanged(String type, String key, String etag, boolean preview) throws ThingsboardException, JsonProcessingException {

1
application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java

@ -369,6 +369,7 @@ public class WidgetTypeController extends AutoCommitController {
String typeFqn = fqn.substring(scopeQualifier.length() + 1);
WidgetType widgetType = widgetTypeService.findWidgetTypeByTenantIdAndFqn(tenantId, typeFqn);
checkNotNull(widgetType);
accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, Operation.READ, widgetType.getId(), widgetType);
return widgetType;
}

11
application/src/main/java/org/thingsboard/server/service/resource/DefaultTbImageService.java

@ -17,10 +17,10 @@ package org.thingsboard.server.service.resource;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.TbImageDeleteResult;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.User;
@ -90,12 +90,15 @@ public class DefaultTbImageService extends AbstractTbEntityService implements Tb
}
@Override
public void delete(TbResourceInfo imageInfo, User user) {
public TbImageDeleteResult delete(TbResourceInfo imageInfo, User user, boolean force) {
TenantId tenantId = imageInfo.getTenantId();
TbResourceId imageId = imageInfo.getId();
try {
imageService.deleteImage(tenantId, imageId);
notificationEntityService.logEntityAction(tenantId, imageId, imageInfo, ActionType.DELETED, user, imageId.toString());
TbImageDeleteResult result = imageService.deleteImage(imageInfo, force);
if (result.isSuccess()) {
notificationEntityService.logEntityAction(tenantId, imageId, imageInfo, ActionType.DELETED, user, imageId.toString());
}
return result;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, imageId, ActionType.DELETED, user, e, imageId.toString());
throw e;

3
application/src/main/java/org/thingsboard/server/service/resource/TbImageService.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.service.resource;
import org.thingsboard.server.common.data.TbImageDeleteResult;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.User;
@ -25,7 +26,7 @@ public interface TbImageService {
TbResourceInfo save(TbResourceInfo imageInfo, User user);
void delete(TbResourceInfo imageInfo, User user);
TbImageDeleteResult delete(TbResourceInfo imageInfo, User user, boolean force);
String getETag(ImageCacheKey imageCacheKey);

3
common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ImageService.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.resource;
import org.thingsboard.server.common.data.TbImageDeleteResult;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.id.TbResourceId;
@ -40,7 +41,7 @@ public interface ImageService {
byte[] getImagePreview(TenantId tenantId, TbResourceId imageId);
void deleteImage(TenantId tenantId, TbResourceId imageId);
TbImageDeleteResult deleteImage(TbResourceInfo imageInfo, boolean force);
List<TbResourceInfo> findSimilarImagesByTenantIdAndKeyStartingWith(TenantId tenantId, byte[] data, String imageKeyStartingWith);

2
common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java

@ -56,6 +56,8 @@ public interface ResourceService extends EntityDaoService {
void deleteResource(TenantId tenantId, TbResourceId resourceId);
void deleteResource(TenantId tenantId, TbResourceId resourceId, boolean force);
void deleteResourcesByTenantId(TenantId tenantId);
long sumDataSizeByTenantId(TenantId tenantId);

32
common/data/src/main/java/org/thingsboard/server/common/data/TbImageDeleteResult.java

@ -0,0 +1,32 @@
/**
* 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.common.data;
import lombok.Builder;
import lombok.Data;
import org.thingsboard.server.common.data.id.HasId;
import java.util.List;
import java.util.Map;
@Data
@Builder
public class TbImageDeleteResult {
private boolean success;
private Map<String, List<? extends HasId<?>>> affectedEntities;
}

29
dao/src/main/java/org/thingsboard/server/dao/ImageContainerDao.java

@ -0,0 +1,29 @@
/**
* 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.dao;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.List;
public interface ImageContainerDao<T extends HasId<?>> {
List<T> findByTenantAndImageLink(TenantId tenantId, String imageUrl, int limit);
List<T> findByImageLink(String imageUrl, int limit);
}

2
dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java

@ -24,8 +24,10 @@ 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.util.TbPair;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import org.thingsboard.server.dao.ImageContainerDao;
import org.thingsboard.server.dao.TenantEntityDao;
import java.util.List;

4
dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileDao.java

@ -21,12 +21,14 @@ import org.thingsboard.server.common.data.id.AssetProfileId;
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.widget.WidgetsBundle;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import org.thingsboard.server.dao.ImageContainerDao;
import java.util.UUID;
public interface AssetProfileDao extends Dao<AssetProfile>, ExportableEntityDao<AssetProfileId, AssetProfile> {
public interface AssetProfileDao extends Dao<AssetProfile>, ExportableEntityDao<AssetProfileId, AssetProfile>, ImageContainerDao<AssetProfileInfo> {
AssetProfileInfo findAssetProfileInfoById(TenantId tenantId, UUID assetProfileId);

7
dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardInfoDao.java

@ -16,16 +16,20 @@
package org.thingsboard.server.dao.dashboard;
import org.thingsboard.server.common.data.DashboardInfo;
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.widget.WidgetTypeInfo;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ImageContainerDao;
import java.util.List;
import java.util.UUID;
/**
* The Interface DashboardInfoDao.
*/
public interface DashboardInfoDao extends Dao<DashboardInfo> {
public interface DashboardInfoDao extends Dao<DashboardInfo>, ImageContainerDao<DashboardInfo> {
/**
* Find dashboards by tenantId and page link.
@ -78,4 +82,5 @@ public interface DashboardInfoDao extends Dao<DashboardInfo> {
DashboardInfo findFirstByTenantIdAndName(UUID tenantId, String name);
String findTitleById(UUID tenantId, UUID dashboardId);
}

4
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java

@ -17,16 +17,18 @@ package org.thingsboard.server.dao.device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceProfileInfo;
import org.thingsboard.server.common.data.asset.AssetProfileInfo;
import org.thingsboard.server.common.data.id.DeviceProfileId;
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.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import org.thingsboard.server.dao.ImageContainerDao;
import java.util.UUID;
public interface DeviceProfileDao extends Dao<DeviceProfile>, ExportableEntityDao<DeviceProfileId, DeviceProfile> {
public interface DeviceProfileDao extends Dao<DeviceProfile>, ExportableEntityDao<DeviceProfileId, DeviceProfile>, ImageContainerDao<DeviceProfileInfo> {
DeviceProfileInfo findDeviceProfileInfoById(TenantId tenantId, UUID deviceProfileId);

69
dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java

@ -18,23 +18,40 @@ package org.thingsboard.server.dao.resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.common.util.RegexUtils;
import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ImageDescriptor;
import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.TbImageDeleteResult;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.TbResourceInfoFilter;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TbResourceId;
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.widget.WidgetTypeInfo;
import org.thingsboard.server.dao.ImageContainerDao;
import org.thingsboard.server.dao.asset.AssetProfileDao;
import org.thingsboard.server.dao.dashboard.DashboardInfoDao;
import org.thingsboard.server.dao.device.DeviceProfileDao;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.service.validator.ResourceDataValidator;
import org.thingsboard.server.dao.util.ImageUtils;
import org.thingsboard.server.dao.util.ImageUtils.ProcessedImage;
import org.thingsboard.server.dao.widget.WidgetTypeDao;
import org.thingsboard.server.dao.widget.WidgetsBundleDao;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
@ -43,10 +60,34 @@ import java.util.regex.Pattern;
@Slf4j
public class BaseImageService extends BaseResourceService implements ImageService {
private static final int MAX_ENTITIES_TO_FIND = 10;
@Autowired
private AssetProfileDao assetProfileDao;
@Autowired
private DeviceProfileDao deviceProfileDao;
@Autowired
private WidgetsBundleDao widgetsBundleDao;
@Autowired
private WidgetTypeDao widgetTypeDao;
@Autowired
private DashboardInfoDao dashboardInfoDao;
private final Map<EntityType, ImageContainerDao<?>> imageContainerDaoMap = new HashMap<>();
public BaseImageService(TbResourceDao resourceDao, TbResourceInfoDao resourceInfoDao, ResourceDataValidator resourceValidator) {
super(resourceDao, resourceInfoDao, resourceValidator);
}
@PostConstruct
public void init() {
imageContainerDaoMap.put(EntityType.WIDGET_TYPE, widgetTypeDao);
imageContainerDaoMap.put(EntityType.WIDGETS_BUNDLE, widgetsBundleDao);
imageContainerDaoMap.put(EntityType.DEVICE_PROFILE, deviceProfileDao);
imageContainerDaoMap.put(EntityType.ASSET_PROFILE, assetProfileDao);
imageContainerDaoMap.put(EntityType.DASHBOARD, dashboardInfoDao);
}
@Transactional
@Override
public TbResourceInfo saveImage(TbResource image) throws Exception {
@ -147,8 +188,32 @@ public class BaseImageService extends BaseResourceService implements ImageServic
}
@Override
public void deleteImage(TenantId tenantId, TbResourceId imageId) {
deleteResource(tenantId, imageId);
public TbImageDeleteResult deleteImage(TbResourceInfo imageInfo, boolean force) {
var tenantId = imageInfo.getTenantId();
var imageId = imageInfo.getId();
log.trace("Executing deleteImage [{}] [{}]", tenantId, imageId);
Validator.validateId(imageId, INCORRECT_RESOURCE_ID + imageId);
TbImageDeleteResult.TbImageDeleteResultBuilder result = TbImageDeleteResult.builder();
boolean success = true;
if (!force) {
var link = imageInfo.getLink();
Map<String, List<? extends HasId<?>>> affectedEntities = new HashMap<>();
imageContainerDaoMap.forEach((entityType, imageContainerDao) -> {
var entities = tenantId.isSysTenantId() ? imageContainerDao.findByImageLink(link, MAX_ENTITIES_TO_FIND) :
imageContainerDao.findByTenantAndImageLink(tenantId, link, MAX_ENTITIES_TO_FIND);
if (!entities.isEmpty()) {
affectedEntities.put(entityType.name(), entities);
}
});
if (!affectedEntities.isEmpty()) {
success = false;
result.affectedEntities(affectedEntities);
}
}
if (success) {
deleteResource(tenantId, imageId, force);
}
return result.success(success).build();
}
@Override

10
dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java

@ -145,13 +145,21 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
@Override
public void deleteResource(TenantId tenantId, TbResourceId resourceId) {
deleteResource(tenantId, resourceId, false);
}
@Override
public void deleteResource(TenantId tenantId, TbResourceId resourceId, boolean force) {
log.trace("Executing deleteResource [{}] [{}]", tenantId, resourceId);
Validator.validateId(resourceId, INCORRECT_RESOURCE_ID + resourceId);
resourceValidator.validateDelete(tenantId, resourceId);
if (!force) {
resourceValidator.validateDelete(tenantId, resourceId);
}
resourceDao.removeById(tenantId, resourceId.getId());
eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entityId(resourceId).build());
}
@Override
public PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) {
TenantId tenantId = filter.getTenantId();

10
dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetProfileRepository.java

@ -23,7 +23,9 @@ import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.asset.AssetProfileInfo;
import org.thingsboard.server.dao.ExportableEntityRepository;
import org.thingsboard.server.dao.model.sql.AssetProfileEntity;
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
import java.util.List;
import java.util.UUID;
public interface AssetProfileRepository extends JpaRepository<AssetProfileEntity, UUID>, ExportableEntityRepository<AssetProfileEntity> {
@ -60,4 +62,12 @@ public interface AssetProfileRepository extends JpaRepository<AssetProfileEntity
@Query("SELECT externalId FROM AssetProfileEntity WHERE id = :id")
UUID getExternalIdById(@Param("id") UUID id);
@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.image = :imageLink")
List<AssetProfileInfo> findByTenantAndImageLink(@Param("tenantId") UUID tenantId, @Param("imageLink") String imageLink, Pageable page);
@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.image = :imageLink")
List<AssetProfileInfo> findByImageLink(@Param("imageLink") String imageLink, Pageable page);
}

12
dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetProfileDao.java

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.sql.asset;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@ -31,6 +32,7 @@ import org.thingsboard.server.dao.asset.AssetProfileDao;
import org.thingsboard.server.dao.model.sql.AssetProfileEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
@ -118,6 +120,16 @@ public class JpaAssetProfileDao extends JpaAbstractDao<AssetProfileEntity, Asset
.map(AssetProfileId::new).orElse(null);
}
@Override
public List<AssetProfileInfo> findByTenantAndImageLink(TenantId tenantId, String imageLink, int limit) {
return assetProfileRepository.findByTenantAndImageLink(tenantId.getId(), imageLink, PageRequest.of(0, limit));
}
@Override
public List<AssetProfileInfo> findByImageLink(String imageLink, int limit) {
return assetProfileRepository.findByImageLink(imageLink, PageRequest.of(0, limit));
}
@Override
public EntityType getEntityType() {
return EntityType.ASSET_PROFILE;

13
dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/DashboardInfoRepository.java

@ -22,6 +22,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.dao.model.sql.DashboardInfoEntity;
import java.util.List;
import java.util.UUID;
/**
@ -74,4 +75,16 @@ public interface DashboardInfoRepository extends JpaRepository<DashboardInfoEnti
@Query("SELECT di.title FROM DashboardInfoEntity di WHERE di.tenantId = :tenantId AND di.id = :dashboardId")
String findTitleByTenantIdAndId(@Param("tenantId") UUID tenantId, @Param("dashboardId") UUID dashboardId);
@Query(nativeQuery = true,
value = "SELECT * FROM dashboard d WHERE d.tenant_id = :tenantId " +
"and (d.image = :imageLink or d.configuration ILIKE CONCAT('%', :imageLink, '%')) limit :lmt"
)
List<DashboardInfoEntity> findByTenantAndImageLink(@Param("tenantId") UUID tenantId, @Param("imageLink") String imageLink, @Param("lmt") int lmt);
@Query(nativeQuery = true,
value = "SELECT * FROM dashboard d WHERE d.image = :imageLink or d.configuration ILIKE CONCAT('%', :imageLink, '%') limit :lmt"
)
List<DashboardInfoEntity> findByImageLink(@Param("imageLink") String imageLink, @Param("lmt") int lmt);
}

12
dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java

@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.DashboardInfo;
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.page.SortOrder;
@ -31,7 +32,6 @@ import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
/**
@ -123,4 +123,14 @@ public class JpaDashboardInfoDao extends JpaAbstractDao<DashboardInfoEntity, Das
public String findTitleById(UUID tenantId, UUID dashboardId) {
return dashboardInfoRepository.findTitleByTenantIdAndId(tenantId, dashboardId);
}
@Override
public List<DashboardInfo> findByTenantAndImageLink(TenantId tenantId, String imageLink, int limit) {
return DaoUtil.convertDataList(dashboardInfoRepository.findByTenantAndImageLink(tenantId.getId(), imageLink, limit));
}
@Override
public List<DashboardInfo> findByImageLink(String imageLink, int limit) {
return DaoUtil.convertDataList(dashboardInfoRepository.findByImageLink(imageLink, limit));
}
}

10
dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java

@ -22,9 +22,11 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.DeviceProfileInfo;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.asset.AssetProfileInfo;
import org.thingsboard.server.dao.ExportableEntityRepository;
import org.thingsboard.server.dao.model.sql.DeviceProfileEntity;
import java.util.List;
import java.util.UUID;
public interface DeviceProfileRepository extends JpaRepository<DeviceProfileEntity, UUID>, ExportableEntityRepository<DeviceProfileEntity> {
@ -68,6 +70,14 @@ public interface DeviceProfileRepository extends JpaRepository<DeviceProfileEnti
DeviceProfileEntity findByProvisionDeviceKey(@Param("provisionDeviceKey") String provisionDeviceKey);
@Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.tenantId, d.name, d.image, d.defaultDashboardId, d.type, d.transportType) " +
"FROM DeviceProfileEntity d WHERE d.tenantId = :tenantId AND d.image = :imageLink")
List<DeviceProfileInfo> findByTenantAndImageLink(@Param("tenantId") UUID tenantId, @Param("imageLink") String imageLink, Pageable page);
@Query("SELECT new org.thingsboard.server.common.data.DeviceProfileInfo(d.id, d.tenantId, d.name, d.image, d.defaultDashboardId, d.type, d.transportType) " +
"FROM DeviceProfileEntity d WHERE d.image = :imageLink")
List<DeviceProfileInfo> findByImageLink(@Param("imageLink") String imageLink, Pageable page);
@Query("SELECT externalId FROM DeviceProfileEntity WHERE id = :id")
UUID getExternalIdById(@Param("id") UUID id);

13
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.sql.device;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@ -24,6 +25,7 @@ import org.thingsboard.server.common.data.DeviceProfileInfo;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.asset.AssetProfileInfo;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
@ -34,6 +36,7 @@ import org.thingsboard.server.dao.model.sql.DeviceProfileEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
@ -136,6 +139,16 @@ public class JpaDeviceProfileDao extends JpaAbstractDao<DeviceProfileEntity, Dev
.map(DeviceProfileId::new).orElse(null);
}
@Override
public List<DeviceProfileInfo> findByTenantAndImageLink(TenantId tenantId, String imageLink, int limit) {
return deviceProfileRepository.findByTenantAndImageLink(tenantId.getId(), imageLink, PageRequest.of(0, limit));
}
@Override
public List<DeviceProfileInfo> findByImageLink(String imageLink, int limit) {
return deviceProfileRepository.findByImageLink(imageLink, PageRequest.of(0, limit));
}
@Override
public EntityType getEntityType() {
return EntityType.DEVICE_PROFILE;

10
dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java

@ -236,6 +236,16 @@ public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, Wi
return DaoUtil.pageToPageData(widgetTypeRepository.findAllIds(DaoUtil.toPageable(pageLink)).map(WidgetTypeId::new));
}
@Override
public List<WidgetTypeInfo> findByTenantAndImageLink(TenantId tenantId, String imageUrl, int limit) {
return DaoUtil.convertDataList(widgetTypeInfoRepository.findByTenantAndImageUrl(tenantId.getId(), imageUrl, limit));
}
@Override
public List<WidgetTypeInfo> findByImageLink(String imageUrl, int limit) {
return DaoUtil.convertDataList(widgetTypeInfoRepository.findByImageUrl(imageUrl, limit));
}
@Override
public EntityType getEntityType() {
return EntityType.WIDGET_TYPE;

10
dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java

@ -146,6 +146,16 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
.map(WidgetsBundleId::new).orElse(null);
}
@Override
public List<WidgetsBundle> findByTenantAndImageLink(TenantId tenantId, String imageUrl, int limit) {
return DaoUtil.convertDataList(widgetsBundleRepository.findByTenantAndImageUrl(tenantId.getId(), imageUrl, limit));
}
@Override
public List<WidgetsBundle> findByImageLink(String imageUrl, int limit) {
return DaoUtil.convertDataList(widgetsBundleRepository.findByImageUrl(imageUrl, limit));
}
@Override
public EntityType getEntityType() {
return EntityType.WIDGETS_BUNDLE;

13
dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java

@ -194,4 +194,17 @@ public interface WidgetTypeInfoRepository extends JpaRepository<WidgetTypeInfoEn
@Param("widgetTypes") List<String> widgetTypes,
Pageable pageable);
@Query(nativeQuery = true,
value = "SELECT * FROM widget_type_info_view wti WHERE wti.id IN " +
"(select id from widget_type where tenant_id = :tenantId " +
"and (image = :imageLink or descriptor ILIKE CONCAT('%', :imageLink, '%')) limit :lmt)"
)
List<WidgetTypeInfoEntity> findByTenantAndImageUrl(@Param("tenantId") UUID tenantId, @Param("imageLink") String imageLink, @Param("lmt") int lmt);
@Query(nativeQuery = true,
value = "SELECT * FROM widget_type_info_view wti WHERE wti.id IN " +
"(select id from widget_type where image = :imageLink or descriptor ILIKE CONCAT('%', :imageLink, '%') limit :lmt)"
)
List<WidgetTypeInfoEntity> findByImageUrl(@Param("imageLink") String imageLink, @Param("lmt") int lmt);
}

6
dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java

@ -21,6 +21,7 @@ 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.WidgetTypeInfoEntity;
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
import java.util.List;
@ -133,4 +134,9 @@ public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEnti
@Query("SELECT externalId FROM WidgetsBundleEntity WHERE id = :id")
UUID getExternalIdById(@Param("id") UUID id);
@Query(nativeQuery = true, value = "SELECT * FROM widgets_bundle wb WHERE wb.tenant_id = :tenantId and wb.image = :imageLink limit :lmt")
List<WidgetsBundleEntity> findByTenantAndImageUrl(@Param("tenantId") UUID tenantId, @Param("imageLink") String imageLink, @Param("lmt") int lmt);
@Query(nativeQuery = true, value = "SELECT * FROM widgets_bundle wb WHERE wb.image = :imageLink limit :lmt")
List<WidgetsBundleEntity> findByImageUrl(@Param("imageLink") String imageLink, @Param("lmt") int lmt);
}

3
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java

@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
import org.thingsboard.server.common.data.widget.WidgetsBundleWidget;
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;
@ -33,7 +34,7 @@ import java.util.UUID;
/**
* The Interface WidgetTypeDao.
*/
public interface WidgetTypeDao extends Dao<WidgetTypeDetails>, ExportableEntityDao<WidgetTypeId, WidgetTypeDetails> {
public interface WidgetTypeDao extends Dao<WidgetTypeDetails>, ExportableEntityDao<WidgetTypeId, WidgetTypeDetails>, ImageContainerDao<WidgetTypeInfo> {
/**
* Save or update widget type object

4
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.widget;
import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.page.PageData;
@ -22,13 +23,14 @@ import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.ExportableEntityDao;
import org.thingsboard.server.dao.ImageContainerDao;
import java.util.UUID;
/**
* The Interface WidgetsBundleDao.
*/
public interface WidgetsBundleDao extends Dao<WidgetsBundle>, ExportableEntityDao<WidgetsBundleId, WidgetsBundle> {
public interface WidgetsBundleDao extends Dao<WidgetsBundle>, ExportableEntityDao<WidgetsBundleId, WidgetsBundle>, ImageContainerDao<WidgetsBundle> {
/**
* Save or update widgets bundle object

23
dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java

@ -110,6 +110,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
widgetType.setName("WIDGET_TYPE_" + number);
widgetType.setDescription("WIDGET_TYPE_DESCRIPTION" + number);
widgetType.setFqn("FQN_" + number);
widgetType.setImage("/image/system/logo.png");
var descriptor = JacksonUtil.newObjectNode();
descriptor.put("type", number % 2 == 0 ? "latest" : "static");
widgetType.setDescriptor(descriptor);
@ -124,6 +125,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
widgetType.setName("WIDGET_TYPE_" + number);
widgetType.setDescription("WIDGET_TYPE_DESCRIPTION" + number);
widgetType.setFqn("FQN_" + number);
widgetType.setImage("/image/tenant/logo.png");
var descriptor = JacksonUtil.newObjectNode();
descriptor.put("type", number % 2 == 0 ? "latest" : "static");
widgetType.setDescriptor(descriptor);
@ -332,4 +334,25 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
WidgetType widgetType = widgetTypeDao.findByTenantIdAndFqn(TenantId.SYS_TENANT_ID.getId(), "FQN_0");
assertEquals(result.getId(), widgetType.getId());
}
@Test
public void testFindByTenantAndImageLink() {
var result = widgetTypeDao.findByImageLink("/image/system/logo.png", 5);
assertEquals(3, result.size());
result = widgetTypeDao.findByImageLink("/image/system/logo2.png", 5);
assertEquals(0, result.size());
}
@Test
public void testFindByImageLink() {
TenantId tenantId = new TenantId(UUID.randomUUID());
WidgetTypeDetails details = createAndSaveWidgetType(tenantId, 0, new String[]{"a"});
details.setDescriptor(JacksonUtil.newObjectNode().put("bg", "/image/tenant/widget.png"));
widgetTypeDao.save(tenantId, details);
var result = widgetTypeDao.findByTenantAndImageLink(tenantId, "/image/tenant/widget.png", 3);
assertEquals(1, result.size());
result = widgetTypeDao.findByTenantAndImageLink(tenantId, "/image/tenant/widget2.png", 3);
assertEquals(0, result.size());
widgetTypeDao.removeById(tenantId, details.getUuidId());
}
}

Loading…
Cancel
Save