diff --git a/application/src/main/java/org/thingsboard/server/controller/ImageController.java b/application/src/main/java/org/thingsboard/server/controller/ImageController.java index 7685640929..815adaca5f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ImageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ImageController.java @@ -50,9 +50,10 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; -import org.thingsboard.server.dao.resource.ImageService; -import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.dao.resource.ImageCacheKey; +import org.thingsboard.server.dao.resource.ImageService; +import org.thingsboard.server.dao.service.validator.ResourceDataValidator; +import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.resource.TbImageService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; @@ -77,6 +78,8 @@ public class ImageController extends BaseController { private final ImageService imageService; private final TbImageService tbImageService; + private final ResourceDataValidator resourceValidator; + @Value("${cache.image.systemImagesBrowserTtlInMinutes:0}") private int systemImagesBrowserTtlInMinutes; @Value("${cache.image.tenantImagesBrowserTtlInMinutes:0}") @@ -94,6 +97,7 @@ public class ImageController extends BaseController { TbResource image = new TbResource(); image.setTenantId(user.getTenantId()); accessControlService.checkPermission(user, Resource.TB_RESOURCE, Operation.CREATE, null, image); + resourceValidator.validateResourceSize(user.getTenantId(), null, file.getSize()); image.setFileName(file.getOriginalFilename()); if (StringUtils.isNotEmpty(title)) { @@ -115,6 +119,8 @@ public class ImageController extends BaseController { @PathVariable String key, @RequestPart MultipartFile file) throws Exception { TbResourceInfo imageInfo = checkImageInfo(type, key, Operation.WRITE); + resourceValidator.validateResourceSize(getTenantId(), imageInfo.getId(), file.getSize()); + TbResource image = new TbResource(imageInfo); image.setData(file.getBytes()); image.setFileName(file.getOriginalFilename()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java index 961fffcdc0..80c9376f1c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.service; import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.thingsboard.server.common.data.BaseData; @@ -129,7 +130,7 @@ public abstract class DataValidator> { EntityType entityType) { if (maxSumDataSize > 0) { if (dataDao.sumDataSizeByTenantId(tenantId) + currentDataSize > maxSumDataSize) { - throw new DataValidationException(String.format("%ss total size exceeds the maximum of " + maxSumDataSize + " bytes", entityType.getNormalName())); + throw new DataValidationException(String.format("%ss total size exceeds the maximum of " + FileUtils.byteCountToDisplaySize(maxSumDataSize), entityType.getNormalName())); } } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java index 26d8ab75fb..352966d561 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/ResourceDataValidator.java @@ -15,12 +15,14 @@ */ package org.thingsboard.server.dao.service.validator; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TbResourceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.data.widget.BaseWidgetType; @@ -83,19 +85,8 @@ public class ResourceDataValidator extends DataValidator { if (resource.getResourceType() == null) { throw new DataValidationException("Resource type should be specified!"); } - if (!resource.getTenantId().isSysTenantId() && resource.getData() != null) { - DefaultTenantProfileConfiguration profileConfiguration = tenantProfileCache.get(tenantId).getDefaultProfileConfiguration(); - long maxResourceSize = profileConfiguration.getMaxResourceSize(); - if (maxResourceSize > 0 && resource.getData().length > maxResourceSize) { - throw new IllegalArgumentException("Resource exceeds the maximum size of " + maxResourceSize + " bytes"); - } - long maxSumResourcesDataInBytes = profileConfiguration.getMaxResourcesInBytes(); - int dataSize = resource.getData().length; - if (resource.getId() != null) { - long prevSize = resourceDao.getResourceSize(tenantId, resource.getId()); - dataSize -= prevSize; - } - validateMaxSumDataSizePerTenant(tenantId, resourceDao, maxSumResourcesDataInBytes, dataSize, TB_RESOURCE); + if (resource.getData() != null) { + validateResourceSize(resource.getTenantId(), resource.getId(), resource.getData().length); } if (StringUtils.isEmpty(resource.getFileName())) { throw new DataValidationException("Resource file name should be specified!"); @@ -108,6 +99,22 @@ public class ResourceDataValidator extends DataValidator { } } + public void validateResourceSize(TenantId tenantId, TbResourceId resourceId, long dataSize) { + if (!tenantId.isSysTenantId()) { + DefaultTenantProfileConfiguration profileConfiguration = tenantProfileCache.get(tenantId).getDefaultProfileConfiguration(); + long maxResourceSize = profileConfiguration.getMaxResourceSize(); + if (maxResourceSize > 0 && dataSize > maxResourceSize) { + throw new IllegalArgumentException("Resource exceeds the maximum size of " + FileUtils.byteCountToDisplaySize(maxResourceSize)); + } + long maxSumResourcesDataInBytes = profileConfiguration.getMaxResourcesInBytes(); + if (resourceId != null) { + long prevSize = resourceDao.getResourceSize(tenantId, resourceId); + dataSize -= prevSize; + } + validateMaxSumDataSizePerTenant(tenantId, resourceDao, maxSumResourcesDataInBytes, dataSize, TB_RESOURCE); + } + } + @Override public void validateDelete(TenantId tenantId, EntityId resourceId) { List widgets = widgetTypeDao.findWidgetTypesInfosByTenantIdAndResourceId(tenantId.getId(),