ImageController draft

This commit is contained in:
ViacheslavKlimov 2023-11-14 12:03:26 +02:00
parent 7489b87fa5
commit 7d4729451a
14 changed files with 382 additions and 39 deletions

View File

@ -0,0 +1,184 @@
/**
* 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.controller;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.exception.ThingsboardException;
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.security.Authority;
import org.thingsboard.server.dao.resource.ImageService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.resource.TbImageService;
import org.thingsboard.server.service.security.permission.Operation;
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;
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.SORT_ORDER_ALLOWABLE_VALUES;
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
@Slf4j
@RestController
@TbCoreComponent
@RequiredArgsConstructor
public class ImageController extends BaseController {
private final ImageService imageService;
private final TbImageService tbImageService;
private static final String IMAGE_URL = "/api/images/{type}/{key}";
private static final String SYSTEM_IMAGE = "system";
private static final String TENANT_IMAGE = "tenant";
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@PostMapping("/api/image")
public TbResourceInfo uploadImage(MultipartFile file) {
// imageService.saveImage()
return null;
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@PutMapping(IMAGE_URL)
public TbResourceInfo updateImage(MultipartFile file) {
return null;
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@PutMapping(IMAGE_URL + "/info")
public TbResourceInfo updateImageInfo(@RequestBody TbResourceInfo imageInfo) {
return null;
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@GetMapping(value = IMAGE_URL, produces = "image/*")
public ResponseEntity<ByteArrayResource> downloadImage(@PathVariable String type,
@PathVariable String key,
@RequestHeader(name = HttpHeaders.IF_NONE_MATCH, required = false) String etag) throws ThingsboardException {
TenantId tenantId = getTenantId(type);
TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key);
return downloadIfChanged(etag, imageInfo, () -> imageService.getImageData(tenantId, imageInfo.getId()), imageInfo.getMediaType());
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@GetMapping(value = IMAGE_URL + "/preview", produces = "image/png")
public ResponseEntity<ByteArrayResource> downloadImagePreview(@PathVariable String type,
@PathVariable String key,
@RequestHeader(name = HttpHeaders.IF_NONE_MATCH, required = false) String etag) throws ThingsboardException {
TenantId tenantId = getTenantId(type);
TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key);
return downloadIfChanged(etag, imageInfo, () -> imageService.getImagePreview(tenantId, imageInfo.getId()), imageInfo.getMediaType());
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@GetMapping(IMAGE_URL + "/info")
public TbResourceInfo getImageInfo(@PathVariable String type,
@PathVariable String key) throws ThingsboardException {
TenantId tenantId = getTenantId(type);
TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key);
return checkEntity(getCurrentUser(), imageInfo, Operation.READ);
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping("/images")
public PageData<TbResourceInfo> getImages(@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);
TenantId tenantId = getTenantId();
if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) {
return checkNotNull(imageService.getImagesByTenantId(tenantId, pageLink));
} else {
return checkNotNull(imageService.getAllImagesByTenantId(tenantId, pageLink));
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@DeleteMapping(IMAGE_URL)
public void deleteImage(@PathVariable String type,
@PathVariable String key) throws ThingsboardException {
TenantId tenantId = getTenantId(type);
TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key);
checkEntity(getCurrentUser(), imageInfo, Operation.DELETE);
tbImageService.delete(imageInfo, getCurrentUser());
}
private ResponseEntity<ByteArrayResource> downloadIfChanged(String etag, TbResourceInfo resourceInfo,
Supplier<byte[]> dataSupplier, String mediaType) throws ThingsboardException {
checkEntity(getCurrentUser(), resourceInfo, Operation.READ);
if (etag != null) {
if (etag.equals(resourceInfo.getEtag())) {
return ResponseEntity.status(HttpStatus.NOT_MODIFIED)
.eTag(etag)
.build();
}
}
byte[] data = dataSupplier.get();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + resourceInfo.getFileName())
.header("x-filename", resourceInfo.getFileName())
.contentLength(data.length)
.header("Content-Type", mediaType)
.cacheControl(CacheControl.noCache())
.eTag(resourceInfo.getEtag())
.body(new ByteArrayResource(data));
}
private TenantId getTenantId(String imageType) throws ThingsboardException {
TenantId tenantId;
if (imageType.equals(TENANT_IMAGE)) {
tenantId = getTenantId();
} else if (imageType.equals(SYSTEM_IMAGE)) {
tenantId = TenantId.SYS_TENANT_ID;
} else {
throw new IllegalArgumentException("Invalid image URL");
}
return tenantId;
}
}

View File

@ -54,7 +54,10 @@ import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import java.util.Base64; import java.util.Base64;
import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER; import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER;
@ -224,9 +227,14 @@ public class TbResourceController extends BaseController {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
TbResourceInfoFilter.TbResourceInfoFilterBuilder filter = TbResourceInfoFilter.builder(); TbResourceInfoFilter.TbResourceInfoFilterBuilder filter = TbResourceInfoFilter.builder();
filter.tenantId(getTenantId()); filter.tenantId(getTenantId());
Set<ResourceType> resourceTypes = new HashSet<>();
if (StringUtils.isNotEmpty(resourceType)) { if (StringUtils.isNotEmpty(resourceType)) {
filter.resourceType(ResourceType.valueOf(resourceType)); resourceTypes.add(ResourceType.valueOf(resourceType));
} else {
Collections.addAll(resourceTypes, ResourceType.values());
resourceTypes.remove(ResourceType.IMAGE);
} }
filter.resourceTypes(resourceTypes);
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
return checkNotNull(resourceService.findTenantResourcesByTenantId(filter.build(), pageLink)); return checkNotNull(resourceService.findTenantResourcesByTenantId(filter.build(), pageLink));
} else { } else {

View File

@ -0,0 +1,30 @@
package org.thingsboard.server.service.resource;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.dao.resource.ImageService;
import org.thingsboard.server.queue.util.TbCoreComponent;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class DefaultTbImageService implements TbImageService {
private final ImageService imageService;
@Override
public TbResource save(TbResourceInfo imageInfo, MultipartFile imageFile, User user) {
return null;
}
@Override
public void delete(TbResourceInfo imageInfo, User user) {
}
}

View File

@ -0,0 +1,14 @@
package org.thingsboard.server.service.resource;
import org.springframework.web.multipart.MultipartFile;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.User;
public interface TbImageService {
TbResource save(TbResourceInfo imageInfo, MultipartFile imageFile, User user);
void delete(TbResourceInfo imageInfo, User user);
}

View File

@ -0,0 +1,28 @@
package org.thingsboard.server.dao.resource;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
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;
public interface ImageService {
TbResourceInfo saveImage(TbResource image);
TbResourceInfo saveImageInfo(TbResourceInfo imageInfo);
TbResourceInfo getImageInfoByTenantIdAndKey(TenantId tenantId, String key);
PageData<TbResourceInfo> getImagesByTenantId(TenantId tenantId, PageLink pageLink);
PageData<TbResourceInfo> getAllImagesByTenantId(TenantId tenantId, PageLink pageLink);
byte[] getImageData(TenantId tenantId, TbResourceId imageId);
byte[] getImagePreview(TenantId tenantId, TbResourceId imageId);
String getImageLink(TbResourceInfo imageInfo);
}

View File

@ -62,6 +62,4 @@ public interface ResourceService extends EntityDaoService {
List<TbResourceInfo> findByTenantIdAndDataAndKeyStartingWith(TenantId tenantId, byte[] data, String query); List<TbResourceInfo> findByTenantIdAndDataAndKeyStartingWith(TenantId tenantId, byte[] data, String query);
String getResourceLink(TbResourceInfo resourceInfo);
} }

View File

@ -19,11 +19,13 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import java.util.Set;
@Data @Data
@Builder @Builder
public class TbResourceInfoFilter { public class TbResourceInfoFilter {
private TenantId tenantId; private TenantId tenantId;
private ResourceType resourceType; private Set<ResourceType> resourceTypes;
} }

View File

@ -0,0 +1,84 @@
package org.thingsboard.server.dao.resource;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.ResourceType;
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.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.dao.service.validator.ResourceDataValidator;
import java.util.Set;
@Service
public class BaseImageService extends BaseResourceService implements ImageService {
public BaseImageService(TbResourceDao resourceDao, TbResourceInfoDao resourceInfoDao, ResourceDataValidator resourceValidator) {
super(resourceDao, resourceInfoDao, resourceValidator);
}
@Override
public TbResourceInfo saveImage(TbResource image) {
resourceValidator.validate(image, TbResourceInfo::getTenantId);
if (image.getData() != null) {
}
// generate preview, etc.
return saveResource(image, false);
}
@Override
public TbResourceInfo saveImageInfo(TbResourceInfo imageInfo) {
return null;
}
@Override
public TbResourceInfo getImageInfoByTenantIdAndKey(TenantId tenantId, String key) {
return findResourceInfoByTenantIdAndKey(tenantId, ResourceType.IMAGE, key);
}
@Override
public PageData<TbResourceInfo> getImagesByTenantId(TenantId tenantId, PageLink pageLink) {
TbResourceInfoFilter filter = TbResourceInfoFilter.builder()
.tenantId(tenantId)
.resourceTypes(Set.of(ResourceType.IMAGE))
.build();
return findTenantResourcesByTenantId(filter, pageLink);
}
@Override
public PageData<TbResourceInfo> getAllImagesByTenantId(TenantId tenantId, PageLink pageLink) {
TbResourceInfoFilter filter = TbResourceInfoFilter.builder()
.tenantId(tenantId)
.resourceTypes(Set.of(ResourceType.IMAGE))
.build();
return findAllTenantResourcesByTenantId(filter, pageLink);
}
@Override
public byte[] getImageData(TenantId tenantId, TbResourceId imageId) {
return resourceDao.getResourceData(tenantId, imageId);
}
@Override
public byte[] getImagePreview(TenantId tenantId, TbResourceId imageId) {
return new byte[0];
}
@Override
public String getImageLink(TbResourceInfo imageInfo) {
String link = "/api/images/";
if (imageInfo.getTenantId().isSysTenantId()) {
link += "system/";
} else {
link += "tenant/";
}
link += imageInfo.getResourceKey();
return link;
}
}

View File

@ -57,9 +57,9 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
public class BaseResourceService extends AbstractCachedEntityService<ResourceInfoCacheKey, TbResourceInfo, ResourceInfoEvictEvent> implements ResourceService { public class BaseResourceService extends AbstractCachedEntityService<ResourceInfoCacheKey, TbResourceInfo, ResourceInfoEvictEvent> implements ResourceService {
public static final String INCORRECT_RESOURCE_ID = "Incorrect resourceId "; public static final String INCORRECT_RESOURCE_ID = "Incorrect resourceId ";
private final TbResourceDao resourceDao; protected final TbResourceDao resourceDao;
private final TbResourceInfoDao resourceInfoDao; protected final TbResourceInfoDao resourceInfoDao;
private final ResourceDataValidator resourceValidator; protected final ResourceDataValidator resourceValidator;
@Override @Override
public TbResource saveResource(TbResource resource, boolean doValidate) { public TbResource saveResource(TbResource resource, boolean doValidate) {
@ -67,20 +67,10 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
if (doValidate) { if (doValidate) {
resourceValidator.validate(resource, TbResourceInfo::getTenantId); resourceValidator.validate(resource, TbResourceInfo::getTenantId);
} }
TenantId tenantId = resource.getTenantId(); TenantId tenantId = resource.getTenantId();
TbResourceId resourceId = resource.getId(); TbResourceId resourceId = resource.getId();
if (resourceId == null) {
UUID uuid = Uuids.timeBased();
resource.setId(new TbResourceId(uuid));
resource.setCreatedTime(Uuids.unixTimestamp(uuid));
}
if (resource.getData() != null) { if (resource.getData() != null) {
resource.setEtag(calculateEtag(resource.getData())); resource.setEtag(calculateEtag(resource.getData()));
if (resource.getResourceType() == ResourceType.IMAGE) {
// FIXME: skip SVG (?)
}
} }
try { try {
TbResource saved; TbResource saved;
@ -225,17 +215,7 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
return resourceInfoDao.findByTenantIdAndEtagAndKeyStartingWith(tenantId, etag, query); return resourceInfoDao.findByTenantIdAndEtagAndKeyStartingWith(tenantId, etag, query);
} }
@Override protected String calculateEtag(byte[] data) {
public String getResourceLink(TbResourceInfo resourceInfo) {
String link = "/api/images/";
if (resourceInfo.getTenantId().isSysTenantId()) {
link += "system/";
}
link += resourceInfo.getResourceKey();
return link;
}
private String calculateEtag(byte[] data) {
return Hashing.sha256().hashBytes(data).toString(); return Hashing.sha256().hashBytes(data).toString();
} }

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.dao.resource;
import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -39,4 +40,7 @@ public interface TbResourceDao extends Dao<TbResource>, TenantEntityWithDataDao
ResourceType resourceType, ResourceType resourceType,
String[] objectIds, String[] objectIds,
String searchText); String searchText);
byte[] getResourceData(TenantId tenantId, TbResourceId resourceId);
} }

View File

@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -31,7 +32,6 @@ import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
@Slf4j @Slf4j
@ -94,6 +94,11 @@ public class JpaTbResourceDao extends JpaAbstractDao<TbResourceEntity, TbResourc
resourceType.name(), objectIds)); resourceType.name(), objectIds));
} }
@Override
public byte[] getResourceData(TenantId tenantId, TbResourceId resourceId) {
return resourceRepository.getDataById(resourceId.getId());
}
@Override @Override
public Long sumDataSizeByTenantId(TenantId tenantId) { public Long sumDataSizeByTenantId(TenantId tenantId) {
return resourceRepository.sumDataSizeByTenantId(tenantId.getId()); return resourceRepository.sumDataSizeByTenantId(tenantId.getId());

View File

@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.TbResourceInfoFilter;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.util.CollectionsUtil;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.TbResourceInfoEntity; import org.thingsboard.server.dao.model.sql.TbResourceInfoEntity;
import org.thingsboard.server.dao.resource.TbResourceInfoDao; import org.thingsboard.server.dao.resource.TbResourceInfoDao;
@ -34,6 +35,7 @@ import org.thingsboard.server.dao.util.SqlDao;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
@Slf4j @Slf4j
@Component @Component
@ -55,23 +57,22 @@ public class JpaTbResourceInfoDao extends JpaAbstractDao<TbResourceInfoEntity, T
@Override @Override
public PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) { public PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) {
ResourceType resourceType = filter.getResourceType();
return DaoUtil.toPageData(resourceInfoRepository return DaoUtil.toPageData(resourceInfoRepository
.findAllTenantResourcesByTenantId( .findAllTenantResourcesByTenantId(
filter.getTenantId().getId(), filter.getTenantId().getId(), TenantId.NULL_UUID,
TenantId.NULL_UUID, CollectionsUtil.isNotEmpty(filter.getResourceTypes()) ? filter.getResourceTypes()
resourceType == null ? null : resourceType.name(), .stream().map(Enum::name).collect(Collectors.toList()) : null,
Objects.toString(pageLink.getTextSearch(), ""), Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }
@Override @Override
public PageData<TbResourceInfo> findTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) { public PageData<TbResourceInfo> findTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) {
ResourceType resourceType = filter.getResourceType();
return DaoUtil.toPageData(resourceInfoRepository return DaoUtil.toPageData(resourceInfoRepository
.findTenantResourcesByTenantId( .findTenantResourcesByTenantId(
filter.getTenantId().getId(), filter.getTenantId().getId(),
resourceType == null ? null : resourceType.name(), CollectionsUtil.isNotEmpty(filter.getResourceTypes()) ? filter.getResourceTypes()
.stream().map(Enum::name).collect(Collectors.toList()) : null,
pageLink.getTextSearch(), pageLink.getTextSearch(),
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }

View File

@ -22,6 +22,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.thingsboard.server.dao.model.sql.TbResourceInfoEntity; import org.thingsboard.server.dao.model.sql.TbResourceInfoEntity;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -36,19 +37,19 @@ public interface TbResourceInfoRepository extends JpaRepository<TbResourceInfoEn
"WHERE sr.tenantId = :tenantId " + "WHERE sr.tenantId = :tenantId " +
"AND tr.resourceType = sr.resourceType " + "AND tr.resourceType = sr.resourceType " +
"AND tr.resourceKey = sr.resourceKey)))" + "AND tr.resourceKey = sr.resourceKey)))" +
"AND (:resourceType IS NULL OR tr.resourceType = :resourceType)") "AND (:resourceTypes IS NULL OR tr.resourceType IN :resourceTypes)")
Page<TbResourceInfoEntity> findAllTenantResourcesByTenantId(@Param("tenantId") UUID tenantId, Page<TbResourceInfoEntity> findAllTenantResourcesByTenantId(@Param("tenantId") UUID tenantId,
@Param("systemAdminId") UUID sysadminId, @Param("systemAdminId") UUID sysadminId,
@Param("resourceType") String resourceType, @Param("resourceTypes") Collection<String> resourceTypes,
@Param("searchText") String searchText, @Param("searchText") String searchText,
Pageable pageable); Pageable pageable);
@Query("SELECT ri FROM TbResourceInfoEntity ri WHERE " + @Query("SELECT ri FROM TbResourceInfoEntity ri WHERE " +
"ri.tenantId = :tenantId " + "ri.tenantId = :tenantId " +
"AND (:resourceType IS NULL OR ri.resourceType = :resourceType)" + "AND (:resourceTypes IS NULL OR ri.resourceType IN :resourceTypes)" +
"AND (:searchText IS NULL OR ilike(ri.title, CONCAT('%', :searchText, '%')) = true)") "AND (:searchText IS NULL OR ilike(ri.title, CONCAT('%', :searchText, '%')) = true)")
Page<TbResourceInfoEntity> findTenantResourcesByTenantId(@Param("tenantId") UUID tenantId, Page<TbResourceInfoEntity> findTenantResourcesByTenantId(@Param("tenantId") UUID tenantId,
@Param("resourceType") String resourceType, @Param("resourceTypes") Collection<String> resourceTypes,
@Param("searchText") String searchText, @Param("searchText") String searchText,
Pageable pageable); Pageable pageable);

View File

@ -80,4 +80,8 @@ public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UU
@Query(value = "SELECT COALESCE(SUM(LENGTH(r.data)), 0) FROM resource r WHERE r.tenant_id = :tenantId", nativeQuery = true) @Query(value = "SELECT COALESCE(SUM(LENGTH(r.data)), 0) FROM resource r WHERE r.tenant_id = :tenantId", nativeQuery = true)
Long sumDataSizeByTenantId(@Param("tenantId") UUID tenantId); Long sumDataSizeByTenantId(@Param("tenantId") UUID tenantId);
@Query("SELECT r.data FROM TbResourceEntity r WHERE r.id = :id")
byte[] getDataById(@Param("id") UUID id);
} }