ImageController draft
This commit is contained in:
parent
7489b87fa5
commit
7d4729451a
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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 {
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
@ -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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
@ -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)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user