diff --git a/application/src/main/data/upgrade/3.2.2/schema_update.sql b/application/src/main/data/upgrade/3.2.2/schema_update.sql index d724ab6152..e68392230a 100644 --- a/application/src/main/data/upgrade/3.2.2/schema_update.sql +++ b/application/src/main/data/upgrade/3.2.2/schema_update.sql @@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS firmware ( content_type varchar(255), checksum_algorithm varchar(32), checksum varchar(1020), - data binary, + data bytea, additional_info varchar, search_text varchar(255), CONSTRAINT firmware_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 4734361770..60c7e51aa4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -717,7 +717,7 @@ public abstract class BaseController { validateId(firmwareId, "Incorrect firmwareId " + firmwareId); Firmware firmware = firmwareService.findFirmwareById(getCurrentUser().getTenantId(), firmwareId); checkNotNull(firmware); - accessControlService.checkPermission(getCurrentUser(), Resource.TB_RESOURCE, operation, firmwareId, firmware); + accessControlService.checkPermission(getCurrentUser(), Resource.FIRMWARE, operation, firmwareId, firmware); return firmware; } catch (Exception e) { throw handleException(e, false); diff --git a/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java b/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java index 4d53be8c07..b844f2ece2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java +++ b/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java @@ -98,7 +98,8 @@ public class FirmwareController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/firmware", method = RequestMethod.POST) @ResponseBody - public FirmwareInfo saveFirmwareInfo(@RequestParam("title") FirmwareInfo firmwareInfo) throws ThingsboardException { + public FirmwareInfo saveFirmwareInfo(@RequestBody FirmwareInfo firmwareInfo) throws ThingsboardException { + firmwareInfo.setTenantId(getTenantId()); checkEntity(firmwareInfo.getId(), firmwareInfo, Resource.FIRMWARE); try { return firmwareService.saveFirmwareInfo(firmwareInfo); @@ -112,7 +113,7 @@ public class FirmwareController extends BaseController { @ResponseBody public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId, @RequestParam String checksum, - @RequestParam String checksumAlgorithm, + @RequestParam(required = false) String checksumAlgorithm, @RequestBody MultipartFile firmwareFile) throws ThingsboardException { checkParameter(FIRMWARE_ID, strFirmwareId); checkParameter("checksum", checksum); @@ -123,6 +124,7 @@ public class FirmwareController extends BaseController { Firmware firmware = new Firmware(firmwareId); firmware.setCreatedTime(info.getCreatedTime()); firmware.setTenantId(getTenantId()); + firmware.setTitle(info.getTitle()); firmware.setVersion(info.getVersion()); firmware.setAdditionalInfo(info.getAdditionalInfo()); @@ -138,7 +140,7 @@ public class FirmwareController extends BaseController { } @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") - @RequestMapping(value = "/firmware", method = RequestMethod.GET) + @RequestMapping(value = "/firmwares", method = RequestMethod.GET) @ResponseBody public PageData getFirmwares(@RequestParam int pageSize, @RequestParam int page, @@ -153,6 +155,23 @@ public class FirmwareController extends BaseController { } } + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/firmwares/{hasData}", method = RequestMethod.GET) + @ResponseBody + public PageData getFirmwares(@PathVariable("hasData") boolean hasData, + @RequestParam int pageSize, + @RequestParam int page, + @RequestParam(required = false) String textSearch, + @RequestParam(required = false) String sortProperty, + @RequestParam(required = false) String sortOrder) throws ThingsboardException { + try { + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); + return checkNotNull(firmwareService.findTenantFirmwaresByTenantIdAndHasData(getTenantId(), hasData, pageLink)); + } catch (Exception e) { + throw handleException(e); + } + } + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java index 140cb14f1a..0fd26fee6e 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java @@ -34,6 +34,8 @@ public interface FirmwareService { PageData findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink); + PageData findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink); + void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); void deleteFirmwaresByTenantId(TenantId tenantId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java index d2fa921d19..bba9583d18 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java @@ -31,6 +31,7 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo private TenantId tenantId; private String title; private String version; + private boolean hasData; public FirmwareInfo() { super(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java index 8e52a5b2a7..9179984a12 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java @@ -70,6 +70,8 @@ public class EntityIdFactory { return new ApiUsageStateId(uuid); case TB_RESOURCE: return new TbResourceId(uuid); + case FIRMWARE: + return new FirmwareId(uuid); } throw new IllegalArgumentException("EntityType " + type + " is not supported!"); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java b/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java index 35d4a3c39c..9f484c8964 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java @@ -109,6 +109,13 @@ public class BaseFirmwareService implements FirmwareService { return firmwareInfoDao.findFirmwareInfoByTenantId(tenantId, pageLink); } + @Override + public PageData findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) { + log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + validatePageLink(pageLink); + return firmwareInfoDao.findFirmwareInfoByTenantIdAndHasData(tenantId, hasData, pageLink); } + @Override public void deleteFirmware(TenantId tenantId, FirmwareId firmwareId) { log.trace("Executing deleteFirmware [{}]", firmwareId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java index cf8259c13c..a2af06ad9a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java @@ -27,4 +27,6 @@ public interface FirmwareInfoDao extends Dao { PageData findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink); + PageData findFirmwareInfoByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 67a4ec9f77..0fb748c83a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -482,6 +482,7 @@ public class ModelConstants { public static final String FIRMWARE_CHECKSUM_COLUMN = "checksum"; public static final String FIRMWARE_DATA_COLUMN = "data"; public static final String FIRMWARE_ADDITIONAL_INFO_COLUMN = ADDITIONAL_INFO_PROPERTY; + public static final String FIRMWARE_HAS_DATA_PROPERTY = "has_data"; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java index 20d1115c52..2da0b110cc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java @@ -124,6 +124,7 @@ public class FirmwareEntity extends BaseSqlEntity implements SearchTex firmware.setChecksum(checksum); if (data != null) { firmware.setData(ByteBuffer.wrap(data)); + firmware.setHasData(true); } firmware.setAdditionalInfo(additionalInfo); return firmware; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java index f0c19c38c8..ea0bd7ffe0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java @@ -20,6 +20,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.FirmwareInfo; import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.TenantId; @@ -31,8 +32,10 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; +import javax.persistence.Transient; import java.util.UUID; +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_HAS_DATA_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN; @@ -62,6 +65,10 @@ public class FirmwareInfoEntity extends BaseSqlEntity implements S @Column(name = SEARCH_TEXT_PROPERTY) private String searchText; +// @Column(name = FIRMWARE_HAS_DATA_PROPERTY, insertable = false, updatable = false) + @Transient + private boolean hasData; + public FirmwareInfoEntity() { super(); } @@ -75,6 +82,16 @@ public class FirmwareInfoEntity extends BaseSqlEntity implements S this.additionalInfo = firmware.getAdditionalInfo(); } + public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, String title, String version, Object additionalInfo, boolean hasData) { + this.id = id; + this.createdTime = createdTime; + this.tenantId = tenantId; + this.title = title; + this.version = version; + this.hasData = hasData; + this.additionalInfo = JacksonUtil.convertValue(additionalInfo, JsonNode.class); + } + @Override public String getSearchTextSource() { return title; @@ -93,6 +110,7 @@ public class FirmwareInfoEntity extends BaseSqlEntity implements S firmware.setTitle(title); firmware.setVersion(version); firmware.setAdditionalInfo(additionalInfo); + firmware.setHasData(hasData); return firmware; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java index dd4a53fe71..8dec49dca9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java @@ -25,10 +25,22 @@ import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity; import java.util.UUID; public interface FirmwareInfoRepository extends CrudRepository { - @Query("SELECT fi FROM FirmwareInfoEntity fi WHERE " + - "fi.tenantId = :tenantId " + - "AND LOWER(fi.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") + @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + + "f.tenantId = :tenantId " + + "AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") Page findAllByTenantId(@Param("tenantId") UUID tenantId, - @Param("searchText") String searchText, - Pageable pageable); + @Param("searchText") String searchText, + Pageable pageable); + + @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " + + "f.tenantId = :tenantId " + + "AND ((f.data IS NOT NULL AND :hasData = true) OR (f.data IS NULL AND :hasData = false ))" + + "AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") + Page findAllByTenantIdAndHasData(@Param("tenantId") UUID tenantId, + @Param("hasData") boolean hasData, + @Param("searchText") String searchText, + Pageable pageable); + + @Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE f.id = :id") + FirmwareInfoEntity findFirmwareInfoById(@Param("id") UUID id); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java index ae61c9ac4f..3b80c1c7e5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java @@ -48,6 +48,21 @@ public class JpaFirmwareInfoDao extends JpaAbstractSearchTextDao findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink) { return DaoUtil.toPageData(firmwareInfoRepository @@ -56,4 +71,14 @@ public class JpaFirmwareInfoDao extends JpaAbstractSearchTextDao findFirmwareInfoByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) { + return DaoUtil.toPageData(firmwareInfoRepository + .findAllByTenantIdAndHasData( + tenantId.getId(), + hasData, + Objects.toString(pageLink.getTextSearch(), ""), + DaoUtil.toPageable(pageLink))); + } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java index 3abb97875b..c4f80c551a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java @@ -127,7 +127,9 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, firmware.getId()); firmware.setAdditionalInfo(JacksonUtil.newObjectNode()); + Assert.assertEquals(foundFirmware.getTitle(), firmware.getTitle()); + Assert.assertTrue(foundFirmware.isHasData()); firmwareService.deleteFirmware(tenantId, savedFirmwareInfo.getId()); } @@ -367,7 +369,10 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); firmware.setChecksum(CHECKSUM); firmware.setData(DATA); - firmwares.add(new FirmwareInfo(firmwareService.saveFirmware(firmware))); + + FirmwareInfo info = new FirmwareInfo(firmwareService.saveFirmware(firmware)); + info.setHasData(true); + firmwares.add(info); } List loadedFirmwares = new ArrayList<>(); @@ -394,4 +399,47 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { Assert.assertTrue(pageData.getData().isEmpty()); } + @Test + public void testFindTenantFirmwaresByTenantIdAndHasData() { + List firmwares = new ArrayList<>(); + for (int i = 0; i < 165; i++) { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setVersion(VERSION + i); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setChecksumAlgorithm(CHECKSUM_ALGORITHM); + firmware.setChecksum(CHECKSUM); + firmware.setData(DATA); + + FirmwareInfo info = new FirmwareInfo(firmwareService.saveFirmware(firmware)); + info.setHasData(true); + firmwares.add(info); + } + + List loadedFirmwares = new ArrayList<>(); + PageLink pageLink = new PageLink(16); + PageData pageData; + do { + pageData = firmwareService.findTenantFirmwaresByTenantIdAndHasData(tenantId, true, pageLink); + loadedFirmwares.addAll(pageData.getData()); + if (pageData.hasNext()) { + pageLink = pageLink.nextPageLink(); + } + } while (pageData.hasNext()); + + Collections.sort(firmwares, idComparator); + Collections.sort(loadedFirmwares, idComparator); + + Assert.assertEquals(firmwares, loadedFirmwares); + + firmwareService.deleteFirmwaresByTenantId(tenantId); + + pageLink = new PageLink(31); + pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, pageLink); + Assert.assertFalse(pageData.hasNext()); + Assert.assertTrue(pageData.getData().isEmpty()); + } + }