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 java.util.Base64;
 | 
			
		||||
 import java.util.Collections;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.function.Supplier;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
        TbResourceInfoFilter.TbResourceInfoFilterBuilder filter = TbResourceInfoFilter.builder();
 | 
			
		||||
        filter.tenantId(getTenantId());
 | 
			
		||||
        Set<ResourceType> resourceTypes = new HashSet<>();
 | 
			
		||||
        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())) {
 | 
			
		||||
            return checkNotNull(resourceService.findTenantResourcesByTenantId(filter.build(), pageLink));
 | 
			
		||||
        } 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);
 | 
			
		||||
 | 
			
		||||
    String getResourceLink(TbResourceInfo resourceInfo);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -19,11 +19,13 @@ import lombok.Builder;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@Builder
 | 
			
		||||
public class TbResourceInfoFilter {
 | 
			
		||||
 | 
			
		||||
    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 static final String INCORRECT_RESOURCE_ID = "Incorrect resourceId ";
 | 
			
		||||
    private final TbResourceDao resourceDao;
 | 
			
		||||
    private final TbResourceInfoDao resourceInfoDao;
 | 
			
		||||
    private final ResourceDataValidator resourceValidator;
 | 
			
		||||
    protected final TbResourceDao resourceDao;
 | 
			
		||||
    protected final TbResourceInfoDao resourceInfoDao;
 | 
			
		||||
    protected final ResourceDataValidator resourceValidator;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbResource saveResource(TbResource resource, boolean doValidate) {
 | 
			
		||||
@ -67,20 +67,10 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
 | 
			
		||||
        if (doValidate) {
 | 
			
		||||
            resourceValidator.validate(resource, TbResourceInfo::getTenantId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        TenantId tenantId = resource.getTenantId();
 | 
			
		||||
        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) {
 | 
			
		||||
            resource.setEtag(calculateEtag(resource.getData()));
 | 
			
		||||
            if (resource.getResourceType() == ResourceType.IMAGE) {
 | 
			
		||||
                // FIXME: skip SVG (?)
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            TbResource saved;
 | 
			
		||||
@ -225,17 +215,7 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
 | 
			
		||||
        return resourceInfoDao.findByTenantIdAndEtagAndKeyStartingWith(tenantId, etag, query);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    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) {
 | 
			
		||||
    protected String calculateEtag(byte[] data) {
 | 
			
		||||
        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.TbResource;
 | 
			
		||||
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;
 | 
			
		||||
@ -39,4 +40,7 @@ public interface TbResourceDao extends Dao<TbResource>, TenantEntityWithDataDao
 | 
			
		||||
                                                            ResourceType resourceType,
 | 
			
		||||
                                                            String[] objectIds,
 | 
			
		||||
                                                            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.ResourceType;
 | 
			
		||||
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.page.PageData;
 | 
			
		||||
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 java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
@ -94,6 +94,11 @@ public class JpaTbResourceDao extends JpaAbstractDao<TbResourceEntity, TbResourc
 | 
			
		||||
                        resourceType.name(), objectIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public byte[] getResourceData(TenantId tenantId, TbResourceId resourceId) {
 | 
			
		||||
        return resourceRepository.getDataById(resourceId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long sumDataSizeByTenantId(TenantId tenantId) {
 | 
			
		||||
        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.page.PageData;
 | 
			
		||||
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.model.sql.TbResourceInfoEntity;
 | 
			
		||||
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.Objects;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Component
 | 
			
		||||
@ -55,23 +57,22 @@ public class JpaTbResourceInfoDao extends JpaAbstractDao<TbResourceInfoEntity, T
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PageData<TbResourceInfo> findAllTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) {
 | 
			
		||||
        ResourceType resourceType = filter.getResourceType();
 | 
			
		||||
        return DaoUtil.toPageData(resourceInfoRepository
 | 
			
		||||
                .findAllTenantResourcesByTenantId(
 | 
			
		||||
                        filter.getTenantId().getId(),
 | 
			
		||||
                        TenantId.NULL_UUID,
 | 
			
		||||
                        resourceType == null ? null : resourceType.name(),
 | 
			
		||||
                        filter.getTenantId().getId(), TenantId.NULL_UUID,
 | 
			
		||||
                        CollectionsUtil.isNotEmpty(filter.getResourceTypes()) ? filter.getResourceTypes()
 | 
			
		||||
                                .stream().map(Enum::name).collect(Collectors.toList()) : null,
 | 
			
		||||
                        Objects.toString(pageLink.getTextSearch(), ""),
 | 
			
		||||
                        DaoUtil.toPageable(pageLink)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PageData<TbResourceInfo> findTenantResourcesByTenantId(TbResourceInfoFilter filter, PageLink pageLink) {
 | 
			
		||||
        ResourceType resourceType = filter.getResourceType();
 | 
			
		||||
        return DaoUtil.toPageData(resourceInfoRepository
 | 
			
		||||
                .findTenantResourcesByTenantId(
 | 
			
		||||
                        filter.getTenantId().getId(),
 | 
			
		||||
                        resourceType == null ? null : resourceType.name(),
 | 
			
		||||
                        CollectionsUtil.isNotEmpty(filter.getResourceTypes()) ? filter.getResourceTypes()
 | 
			
		||||
                                .stream().map(Enum::name).collect(Collectors.toList()) : null,
 | 
			
		||||
                        pageLink.getTextSearch(),
 | 
			
		||||
                        DaoUtil.toPageable(pageLink)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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.TbResourceInfoEntity;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@ -36,19 +37,19 @@ public interface TbResourceInfoRepository extends JpaRepository<TbResourceInfoEn
 | 
			
		||||
            "WHERE sr.tenantId = :tenantId " +
 | 
			
		||||
            "AND tr.resourceType = sr.resourceType " +
 | 
			
		||||
            "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,
 | 
			
		||||
                                                                @Param("systemAdminId") UUID sysadminId,
 | 
			
		||||
                                                                @Param("resourceType") String resourceType,
 | 
			
		||||
                                                                @Param("resourceTypes") Collection<String> resourceTypes,
 | 
			
		||||
                                                                @Param("searchText") String searchText,
 | 
			
		||||
                                                                Pageable pageable);
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT ri FROM TbResourceInfoEntity ri WHERE " +
 | 
			
		||||
            "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)")
 | 
			
		||||
    Page<TbResourceInfoEntity> findTenantResourcesByTenantId(@Param("tenantId") UUID tenantId,
 | 
			
		||||
                                                             @Param("resourceType") String resourceType,
 | 
			
		||||
                                                             @Param("resourceTypes") Collection<String> resourceTypes,
 | 
			
		||||
                                                             @Param("searchText") String searchText,
 | 
			
		||||
                                                             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)
 | 
			
		||||
    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