From b51fee8740223f8bd6172c211d409f30b947ccd0 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 8 Apr 2021 10:30:30 +0300 Subject: [PATCH] created firmware dao --- .../server/controller/BaseController.java | 42 +++ .../server/controller/FirmwareController.java | 147 ++++++++++ .../controller/TbResourceController.java | 8 +- .../service/security/permission/Resource.java | 3 +- .../permission/TenantAdminPermissions.java | 1 + .../server/dao/firmware/FirmwareService.java | 39 +++ .../dao/resource/TbResourceService.java | 2 +- .../server/common/data/Device.java | 14 + .../server/common/data/DeviceProfile.java | 3 + .../server/common/data/EntityType.java | 2 +- .../server/common/data/Firmware.java | 44 +++ .../server/common/data/FirmwareInfo.java | 56 ++++ .../server/common/data/TbResourceInfo.java | 2 + .../server/common/data/id/FirmwareId.java | 44 +++ .../dao/firmware/BaseFirmwareService.java | 162 +++++++++++ .../server/dao/firmware/FirmwareDao.java | 23 ++ .../server/dao/firmware/FirmwareInfoDao.java | 30 ++ .../server/dao/model/ModelConstants.java | 12 + .../dao/model/sql/AbstractDeviceEntity.java | 11 + .../dao/model/sql/DeviceProfileEntity.java | 12 + .../server/dao/model/sql/FirmwareEntity.java | 99 +++++++ .../dao/model/sql/FirmwareInfoEntity.java | 92 ++++++ .../sql/firmware/FirmwareInfoRepository.java | 34 +++ .../dao/sql/firmware/FirmwareRepository.java | 24 ++ .../dao/sql/firmware/JpaFirmwareDao.java | 46 +++ .../dao/sql/firmware/JpaFirmwareInfoDao.java | 59 ++++ .../sql/resource/TbResourceRepository.java | 2 - .../resources/sql/schema-entities-hsql.sql | 19 +- .../main/resources/sql/schema-entities.sql | 21 +- .../server/dao/SqlDaoServiceTestSuite.java | 2 +- .../dao/service/AbstractServiceTest.java | 6 +- .../dao/service/BaseFirmwareServiceTest.java | 271 ++++++++++++++++++ .../service/sql/FirmwareServiceSqlTest.java | 23 ++ .../resources/sql/hsql/drop-all-tables.sql | 1 + .../resources/sql/psql/drop-all-tables.sql | 1 + .../sql/timescale/drop-all-tables.sql | 4 +- 36 files changed, 1341 insertions(+), 20 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/controller/FirmwareController.java create mode 100644 common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/Firmware.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/id/FirmwareId.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareDao.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareRepository.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareDao.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java create mode 100644 dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java create mode 100644 dao/src/test/java/org/thingsboard/server/dao/service/sql/FirmwareServiceSqlTest.java 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 04ea69d419..4734361770 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -24,6 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -37,6 +38,8 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityViewInfo; +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.common.data.FirmwareInfo; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.TbResourceInfo; @@ -61,6 +64,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.EntityViewId; +import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.TbResourceId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; @@ -97,6 +101,7 @@ import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; +import org.thingsboard.server.dao.firmware.FirmwareService; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; import org.thingsboard.server.dao.oauth2.OAuth2Service; @@ -232,6 +237,9 @@ public abstract class BaseController { @Autowired protected TbResourceService resourceService; + @Autowired + protected FirmwareService firmwareService; + @Autowired protected TbQueueProducerProvider producerProvider; @@ -470,6 +478,9 @@ public abstract class BaseController { case TB_RESOURCE: checkResourceId(new TbResourceId(entityId.getId()), operation); return; + case FIRMWARE: + checkFirmwareId(new FirmwareId(entityId.getId()), operation); + return; default: throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); } @@ -701,6 +712,30 @@ public abstract class BaseController { } } + Firmware checkFirmwareId(FirmwareId firmwareId, Operation operation) throws ThingsboardException { + try { + validateId(firmwareId, "Incorrect firmwareId " + firmwareId); + Firmware firmware = firmwareService.findFirmwareById(getCurrentUser().getTenantId(), firmwareId); + checkNotNull(firmware); + accessControlService.checkPermission(getCurrentUser(), Resource.TB_RESOURCE, operation, firmwareId, firmware); + return firmware; + } catch (Exception e) { + throw handleException(e, false); + } + } + + FirmwareInfo checkFirmwareInfoId(FirmwareId firmwareId, Operation operation) throws ThingsboardException { + try { + validateId(firmwareId, "Incorrect firmwareId " + firmwareId); + FirmwareInfo firmwareInfo = firmwareService.findFirmwareInfoById(getCurrentUser().getTenantId(), firmwareId); + checkNotNull(firmwareInfo); + accessControlService.checkPermission(getCurrentUser(), Resource.FIRMWARE, operation, firmwareId, firmwareInfo); + return firmwareInfo; + } catch (Exception e) { + throw handleException(e, false); + } + } + @SuppressWarnings("unchecked") protected I emptyId(EntityType entityType) { return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); @@ -924,4 +959,11 @@ public abstract class BaseController { } } + protected MediaType parseMediaType(String contentType) { + try { + return MediaType.parseMediaType(contentType); + } catch (Exception e) { + return MediaType.APPLICATION_OCTET_STREAM; + } + } } diff --git a/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java b/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java new file mode 100644 index 0000000000..7736abba11 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/FirmwareController.java @@ -0,0 +1,147 @@ +/** + * Copyright © 2016-2021 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 lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.common.data.FirmwareInfo; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.FirmwareId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.security.permission.Operation; + +import java.nio.ByteBuffer; + +@Slf4j +@RestController +@TbCoreComponent +@RequestMapping("/api") +public class FirmwareController extends BaseController { + + public static final String FIRMWARE_ID = "firmwareId"; + + @PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')") + @RequestMapping(value = "/firmware/{firmwareId}/download", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity downloadFirmware(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException { + checkParameter(FIRMWARE_ID, strFirmwareId); + try { + FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); + Firmware firmware = checkFirmwareId(firmwareId, Operation.READ); + + ByteArrayResource resource = new ByteArrayResource(firmware.getData().array()); + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + firmware.getFileName()) + .header("x-filename", firmware.getFileName()) + .contentLength(resource.contentLength()) + .contentType(parseMediaType(firmware.getContentType())) + .body(resource); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/firmware/info/{firmwareId}", method = RequestMethod.GET) + @ResponseBody + public FirmwareInfo getFirmwareInfoById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException { + checkParameter(FIRMWARE_ID, strFirmwareId); + try { + FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); + return checkFirmwareInfoId(firmwareId, Operation.READ); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.GET) + @ResponseBody + public Firmware getFirmwareById(@PathVariable(FIRMWARE_ID) String strFirmwareId) throws ThingsboardException { + checkParameter(FIRMWARE_ID, strFirmwareId); + try { + FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); + return checkFirmwareId(firmwareId, Operation.READ); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/firmware", method = RequestMethod.POST) + @ResponseBody + public Firmware saveFirmware(@RequestParam("title") String title, + @RequestBody MultipartFile firmwareFile) throws ThingsboardException { + checkParameter("title", title); + try { + checkNotNull(firmwareFile); + Firmware firmware = new Firmware(); + firmware.setTenantId(getTenantId()); + firmware.setTitle(title); + firmware.setFileName(firmwareFile.getOriginalFilename()); + firmware.setContentType(firmwareFile.getContentType()); + firmware.setData(ByteBuffer.wrap(firmwareFile.getBytes())); + return firmwareService.saveFirmware(firmware); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/firmware", method = RequestMethod.GET) + @ResponseBody + public PageData getFirmwares(@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.findTenantFirmwaresByTenantId(getTenantId(), pageLink)); + } catch (Exception e) { + throw handleException(e); + } + } + + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") + @RequestMapping(value = "/firmware/{firmwareId}", method = RequestMethod.DELETE) + @ResponseBody + public void deleteResource(@PathVariable("firmwareId") String strFirmwareId) throws ThingsboardException { + checkParameter(FIRMWARE_ID, strFirmwareId); + try { + FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId)); + checkFirmwareInfoId(firmwareId, Operation.DELETE); + firmwareService.deleteFirmware(getTenantId(), firmwareId); + } catch (Exception e) { + throw handleException(e); + } + } + +} \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java index 0190c3e790..adba9827cd 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java @@ -55,12 +55,6 @@ public class TbResourceController extends BaseController { public static final String RESOURCE_ID = "resourceId"; - private final TbResourceService resourceService; - - public TbResourceController(TbResourceService resourceService) { - this.resourceService = resourceService; - } - @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/{resourceId}/download", method = RequestMethod.GET) @ResponseBody @@ -187,7 +181,7 @@ public class TbResourceController extends BaseController { @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.DELETE) @ResponseBody public void deleteResource(@PathVariable("resourceId") String strResourceId) throws ThingsboardException { - checkParameter("resourceId", strResourceId); + checkParameter(RESOURCE_ID, strResourceId); try { TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); TbResource tbResource = checkResourceId(resourceId, Operation.DELETE); diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java index ba53ceea98..b6ac71169e 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java @@ -37,7 +37,8 @@ public enum Resource { TENANT_PROFILE(EntityType.TENANT_PROFILE), DEVICE_PROFILE(EntityType.DEVICE_PROFILE), API_USAGE_STATE(EntityType.API_USAGE_STATE), - TB_RESOURCE(EntityType.TB_RESOURCE); + TB_RESOURCE(EntityType.TB_RESOURCE), + FIRMWARE(EntityType.FIRMWARE); private final EntityType entityType; diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java index c36a70821f..a6fce632b8 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java @@ -42,6 +42,7 @@ public class TenantAdminPermissions extends AbstractPermissions { put(Resource.DEVICE_PROFILE, tenantEntityPermissionChecker); put(Resource.API_USAGE_STATE, tenantEntityPermissionChecker); put(Resource.TB_RESOURCE, tbResourcePermissionChecker); + put(Resource.FIRMWARE, tenantEntityPermissionChecker); } public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker() { 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 new file mode 100644 index 0000000000..bff1a6f806 --- /dev/null +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/firmware/FirmwareService.java @@ -0,0 +1,39 @@ +/** + * Copyright © 2016-2021 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.dao.firmware; + +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.common.data.FirmwareInfo; +import org.thingsboard.server.common.data.id.FirmwareId; +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 FirmwareService { + + Firmware saveFirmware(Firmware firmware); + + Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId); + + FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId); + + PageData findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink); + + void deleteFirmware(TenantId tenantId, FirmwareId firmwareId); + + void deleteFirmwaresByTenantId(TenantId tenantId); +} diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/TbResourceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/TbResourceService.java index 0093b43dfe..d879827008 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/TbResourceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/resource/TbResourceService.java @@ -32,7 +32,7 @@ import java.util.List; public interface TbResourceService { TbResource saveResource(TbResource resource) throws InvalidDDFFileException, IOException; - TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); + TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceKey); TbResource findResourceById(TenantId tenantId, TbResourceId resourceId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Device.java b/common/data/src/main/java/org/thingsboard/server/common/data/Device.java index ad93983cac..54afd813c7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Device.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Device.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.device.data.DeviceData; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.TenantId; import java.io.ByteArrayInputStream; @@ -44,6 +45,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo implemen @JsonIgnore private byte[] deviceDataBytes; + private FirmwareId firmwareId; + public Device() { super(); } @@ -61,6 +64,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo implemen this.label = device.getLabel(); this.deviceProfileId = device.getDeviceProfileId(); this.setDeviceData(device.getDeviceData()); + this.firmwareId = device.getFirmwareId(); } public Device updateDevice(Device device) { @@ -155,6 +159,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo implemen return getName(); } + public FirmwareId getFirmwareId() { + return firmwareId; + } + + public void setFirmwareId(FirmwareId firmwareId) { + this.firmwareId = firmwareId; + } + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -171,6 +183,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo implemen builder.append(", deviceProfileId="); builder.append(deviceProfileId); builder.append(", deviceData="); + builder.append(firmwareId); + builder.append(", firmwareId="); builder.append(deviceData); builder.append(", additionalInfo="); builder.append(getAdditionalInfo()); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java index 8b24cefa71..8a6f50e632 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java @@ -22,6 +22,7 @@ import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; @@ -49,6 +50,8 @@ public class DeviceProfile extends SearchTextBased implements H private byte[] profileDataBytes; private String provisionDeviceKey; + private FirmwareId firmwareId; + public DeviceProfile() { super(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index f289f802d8..36be053789 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; * @author Andrew Shvayka */ public enum EntityType { - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, API_USAGE_STATE, TB_RESOURCE; + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, API_USAGE_STATE, TB_RESOURCE, FIRMWARE; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Firmware.java b/common/data/src/main/java/org/thingsboard/server/common/data/Firmware.java new file mode 100644 index 0000000000..b4155a578a --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Firmware.java @@ -0,0 +1,44 @@ +/** + * Copyright © 2016-2021 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.common.data; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.id.FirmwareId; + +import java.nio.ByteBuffer; + +@Data +@EqualsAndHashCode(callSuper = true) +public class Firmware extends FirmwareInfo { + + private static final long serialVersionUID = 3091601761339422546L; + + private transient ByteBuffer data; + + public Firmware() { + super(); + } + + public Firmware(FirmwareId id) { + super(id); + } + + public Firmware(Firmware firmware) { + super(firmware); + this.data = firmware.getData(); + } +} 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 new file mode 100644 index 0000000000..b950268649 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/FirmwareInfo.java @@ -0,0 +1,56 @@ +/** + * Copyright © 2016-2021 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.common.data; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.server.common.data.id.FirmwareId; +import org.thingsboard.server.common.data.id.TenantId; + +@Slf4j +@Data +@EqualsAndHashCode(callSuper = true) +public class FirmwareInfo extends SearchTextBased implements HasTenantId { + + private static final long serialVersionUID = 3168391583570815419L; + + private TenantId tenantId; + private String title; + private String fileName; + private String contentType; + + public FirmwareInfo() { + super(); + } + + public FirmwareInfo(FirmwareId id) { + super(id); + } + + public FirmwareInfo(FirmwareInfo firmwareInfo) { + super(firmwareInfo); + this.tenantId = firmwareInfo.getTenantId(); + this.title = firmwareInfo.getTitle(); + this.fileName = firmwareInfo.getFileName(); + this.contentType = firmwareInfo.getContentType(); + } + + @Override + public String getSearchText() { + return title; + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java index d72982aeca..7fa869e14f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java @@ -26,6 +26,8 @@ import org.thingsboard.server.common.data.id.TenantId; @EqualsAndHashCode(callSuper = true) public class TbResourceInfo extends SearchTextBased implements HasTenantId { + private static final long serialVersionUID = 7282664529021651736L; + private TenantId tenantId; private String title; private ResourceType resourceType; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/FirmwareId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/FirmwareId.java new file mode 100644 index 0000000000..3cdee53f58 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/FirmwareId.java @@ -0,0 +1,44 @@ +/** + * Copyright © 2016-2021 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.common.data.id; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.thingsboard.server.common.data.EntityType; + +import java.util.UUID; + +public class FirmwareId extends UUIDBased implements EntityId { + + private static final long serialVersionUID = 1L; + + @JsonCreator + public FirmwareId(@JsonProperty("id") UUID id) { + super(id); + } + + public static FirmwareId fromString(String firmwareId) { + return new FirmwareId(UUID.fromString(firmwareId)); + } + + @JsonIgnore + @Override + public EntityType getEntityType() { + return EntityType.FIRMWARE; + } + +} 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 new file mode 100644 index 0000000000..bf1c4f10e6 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/BaseFirmwareService.java @@ -0,0 +1,162 @@ +/** + * Copyright © 2016-2021 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.dao.firmware; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.exception.ConstraintViolationException; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.common.data.FirmwareInfo; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.id.FirmwareId; +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.exception.DataValidationException; +import org.thingsboard.server.dao.service.DataValidator; +import org.thingsboard.server.dao.service.PaginatedRemover; +import org.thingsboard.server.dao.tenant.TenantDao; + +import java.nio.ByteBuffer; +import java.util.Optional; + +import static org.thingsboard.server.dao.service.Validator.validateId; +import static org.thingsboard.server.dao.service.Validator.validatePageLink; + +@Service +@Slf4j +public class BaseFirmwareService implements FirmwareService { + public static final String INCORRECT_FIRMWARE_ID = "Incorrect firmwareId "; + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; + + private final TenantDao tenantDao; + private final FirmwareDao firmwareDao; + private final FirmwareInfoDao firmwareInfoDao; + + public BaseFirmwareService(TenantDao tenantDao, FirmwareDao firmwareDao, FirmwareInfoDao firmwareInfoDao) { + this.tenantDao = tenantDao; + this.firmwareDao = firmwareDao; + this.firmwareInfoDao = firmwareInfoDao; + } + + @Override + public Firmware saveFirmware(Firmware firmware) { + log.trace("Executing saveFirmware [{}]", firmware); + firmwareValidator.validate(firmware, Firmware::getTenantId); + return firmwareDao.save(firmware.getTenantId(), firmware); + } + + @Override + public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) { + log.trace("Executing findFirmwareById [{}]", firmwareId); + validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); + return firmwareDao.findById(tenantId, firmwareId.getId()); + } + + @Override + public FirmwareInfo findFirmwareInfoById(TenantId tenantId, FirmwareId firmwareId) { + log.trace("Executing findFirmwareInfoById [{}]", firmwareId); + validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); + return firmwareInfoDao.findById(tenantId, firmwareId.getId()); + } + + @Override + public PageData findTenantFirmwaresByTenantId(TenantId tenantId, PageLink pageLink) { + log.trace("Executing findTenantFirmwaresByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + validatePageLink(pageLink); + return firmwareInfoDao.findFirmwareInfoByTenantId(tenantId, pageLink); + } + + @Override + public void deleteFirmware(TenantId tenantId, FirmwareId firmwareId) { + log.trace("Executing deleteFirmware [{}]", firmwareId); + validateId(firmwareId, INCORRECT_FIRMWARE_ID + firmwareId); + try { + firmwareDao.removeById(tenantId, firmwareId.getId()); + } catch (Exception t) { + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device")) { + throw new DataValidationException("The firmware referenced by the devices cannot be deleted!"); + } else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_firmware_device_profile")) { + throw new DataValidationException("The firmware referenced by the device profile cannot be deleted!"); + } else { + throw t; + } + } + } + + @Override + public void deleteFirmwaresByTenantId(TenantId tenantId) { + log.trace("Executing deleteFirmwaresByTenantId, tenantId [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + tenantFirmwareRemover.removeEntities(tenantId, tenantId); + } + + private DataValidator firmwareValidator = new DataValidator<>() { + + @Override + protected void validateDataImpl(TenantId tenantId, Firmware firmware) { + if (firmware.getTenantId() == null) { + throw new DataValidationException("Firmware should be assigned to tenant!"); + } else { + Tenant tenant = tenantDao.findById(firmware.getTenantId(), firmware.getTenantId().getId()); + if (tenant == null) { + throw new DataValidationException("Firmware is referencing to non-existent tenant!"); + } + } + + if (StringUtils.isEmpty(firmware.getTitle())) { + throw new DataValidationException("Firmware title should be specified!"); + } + if (StringUtils.isEmpty(firmware.getFileName())) { + throw new DataValidationException("Firmware file name should be specified!"); + } + if (StringUtils.isEmpty(firmware.getContentType())) { + throw new DataValidationException("Firmware content type should be specified!"); + } + ByteBuffer data = firmware.getData(); + if (data == null || !data.hasArray() || data.array().length == 0) { + throw new DataValidationException("Firmware data should be specified!"); + } + } + }; + + private PaginatedRemover tenantFirmwareRemover = + new PaginatedRemover<>() { + + @Override + protected PageData findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { + return firmwareInfoDao.findFirmwareInfoByTenantId(id, pageLink); + } + + @Override + protected void removeEntity(TenantId tenantId, FirmwareInfo entity) { + deleteFirmware(tenantId, entity.getId()); + } + }; + + protected Optional extractConstraintViolationException(Exception t) { + if (t instanceof ConstraintViolationException) { + return Optional.of((ConstraintViolationException) t); + } else if (t.getCause() instanceof ConstraintViolationException) { + return Optional.of((ConstraintViolationException) (t.getCause())); + } else { + return Optional.empty(); + } + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareDao.java b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareDao.java new file mode 100644 index 0000000000..0cacb47ea0 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareDao.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2021 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.dao.firmware; + +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.dao.Dao; + +public interface FirmwareDao extends Dao { + +} 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 new file mode 100644 index 0000000000..cf8259c13c --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/firmware/FirmwareInfoDao.java @@ -0,0 +1,30 @@ +/** + * Copyright © 2016-2021 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.dao.firmware; + +import org.thingsboard.server.common.data.FirmwareInfo; +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.Dao; + +import java.util.UUID; + +public interface FirmwareInfoDao extends Dao { + + PageData findFirmwareInfoByTenantId(TenantId tenantId, 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 3afae3c081..05af88eeb9 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 @@ -153,6 +153,7 @@ public class ModelConstants { public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; public static final String DEVICE_DEVICE_PROFILE_ID_PROPERTY = "device_profile_id"; public static final String DEVICE_DEVICE_DATA_PROPERTY = "device_data"; + public static final String DEVICE_FIRMWARE_ID_PROPERTY = "firmware_id"; public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; @@ -176,6 +177,7 @@ public class ModelConstants { public static final String DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY = "default_rule_chain_id"; public static final String DEVICE_PROFILE_DEFAULT_QUEUE_NAME_PROPERTY = "default_queue_name"; public static final String DEVICE_PROFILE_PROVISION_DEVICE_KEY = "provision_device_key"; + public static final String DEVICE_PROFILE_FIRMWARE_ID_PROPERTY = "firmware_id"; /** * Cassandra entityView constants. @@ -467,6 +469,16 @@ public class ModelConstants { public static final String RESOURCE_FILE_NAME_COLUMN = "file_name"; public static final String RESOURCE_DATA_COLUMN = "data"; + /** + * Firmware constants. + */ + public static final String FIRMWARE_TABLE_NAME = "firmware"; + public static final String FIRMWARE_TENANT_ID_COLUMN = TENANT_ID_COLUMN; + public static final String FIRMWARE_TITLE_COLUMN = TITLE_PROPERTY; + public static final String FIRMWARE_FILE_NAME_COLUMN = "file_name"; + public static final String FIRMWARE_CONTENT_TYPE_COLUMN = "content_type"; + public static final String FIRMWARE_DATA_COLUMN = "data"; + /** * Cassandra attributes and timeseries constants. */ diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java index 5a4381fa24..8dee576611 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.device.data.DeviceData; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; @@ -73,6 +74,9 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti @Column(name = ModelConstants.DEVICE_DEVICE_PROFILE_ID_PROPERTY, columnDefinition = "uuid") private UUID deviceProfileId; + @Column(name = ModelConstants.DEVICE_FIRMWARE_ID_PROPERTY, columnDefinition = "uuid") + private UUID firmwareId; + @Type(type = "jsonb") @Column(name = ModelConstants.DEVICE_DEVICE_DATA_PROPERTY, columnDefinition = "jsonb") private JsonNode deviceData; @@ -95,6 +99,9 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti if (device.getDeviceProfileId() != null) { this.deviceProfileId = device.getDeviceProfileId().getId(); } + if (device.getFirmwareId() != null) { + this.firmwareId = device.getFirmwareId().getId(); + } this.deviceData = JacksonUtil.convertValue(device.getDeviceData(), ObjectNode.class); this.name = device.getName(); this.type = device.getType(); @@ -114,6 +121,7 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti this.label = deviceEntity.getLabel(); this.searchText = deviceEntity.getSearchText(); this.additionalInfo = deviceEntity.getAdditionalInfo(); + this.firmwareId = deviceEntity.getFirmwareId(); } @Override @@ -138,6 +146,9 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti if (deviceProfileId != null) { device.setDeviceProfileId(new DeviceProfileId(deviceProfileId)); } + if (firmwareId != null) { + device.setFirmwareId(new FirmwareId(firmwareId)); + } device.setDeviceData(JacksonUtil.convertValue(deviceData, DeviceData.class)); device.setName(name); device.setType(type); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java index 0ddf78c8ce..e437c87fdd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.FirmwareId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; @@ -89,6 +90,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity impl @Column(name=ModelConstants.DEVICE_PROFILE_PROVISION_DEVICE_KEY) private String provisionDeviceKey; + @Column(name=ModelConstants.DEVICE_PROFILE_FIRMWARE_ID_PROPERTY) + private UUID firmwareId; + public DeviceProfileEntity() { super(); } @@ -113,6 +117,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity impl } this.defaultQueueName = deviceProfile.getDefaultQueueName(); this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey(); + if (deviceProfile.getFirmwareId() != null) { + this.firmwareId = deviceProfile.getFirmwareId().getId(); + } } @Override @@ -148,6 +155,11 @@ public final class DeviceProfileEntity extends BaseSqlEntity impl } deviceProfile.setDefaultQueueName(defaultQueueName); deviceProfile.setProvisionDeviceKey(provisionDeviceKey); + + if (firmwareId != null) { + deviceProfile.setFirmwareId(new FirmwareId(firmwareId)); + } + return deviceProfile; } } 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 new file mode 100644 index 0000000000..1823c5eae5 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareEntity.java @@ -0,0 +1,99 @@ +/** + * Copyright © 2016-2021 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.dao.model.sql; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.common.data.id.FirmwareId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.SearchTextEntity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.nio.ByteBuffer; +import java.util.UUID; + +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN; +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_DATA_COLUMN; +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN; +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; +import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = FIRMWARE_TABLE_NAME) +public class FirmwareEntity extends BaseSqlEntity implements SearchTextEntity { + + @Column(name = FIRMWARE_TENANT_ID_COLUMN) + private UUID tenantId; + + @Column(name = FIRMWARE_TITLE_COLUMN) + private String title; + + @Column(name = FIRMWARE_FILE_NAME_COLUMN) + private String fileName; + + @Column(name = FIRMWARE_CONTENT_TYPE_COLUMN) + private String contentType; + + @Column(name = FIRMWARE_DATA_COLUMN, columnDefinition = "BINARY") + private byte[] data; + + @Column(name = SEARCH_TEXT_PROPERTY) + private String searchText; + + public FirmwareEntity() { + super(); + } + + public FirmwareEntity(Firmware firmware) { + this.createdTime = firmware.getCreatedTime(); + this.setUuid(firmware.getUuidId()); + this.tenantId = firmware.getTenantId().getId(); + this.title = firmware.getTitle(); + this.fileName = firmware.getFileName(); + this.contentType = firmware.getContentType(); + this.data = firmware.getData().array(); + } + + @Override + public String getSearchTextSource() { + return title; + } + + @Override + public void setSearchText(String searchText) { + this.searchText = searchText; + } + + @Override + public Firmware toData() { + Firmware firmware = new Firmware(new FirmwareId(id)); + firmware.setCreatedTime(createdTime); + firmware.setTenantId(new TenantId(tenantId)); + firmware.setTitle(title); + firmware.setFileName(fileName); + firmware.setContentType(contentType); + firmware.setData(ByteBuffer.wrap(data)); + 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 new file mode 100644 index 0000000000..ec7ee7206f --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/FirmwareInfoEntity.java @@ -0,0 +1,92 @@ +/** + * Copyright © 2016-2021 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.dao.model.sql; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.FirmwareInfo; +import org.thingsboard.server.common.data.id.FirmwareId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.SearchTextEntity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.UUID; + +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_CONTENT_TYPE_COLUMN; +import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME_COLUMN; +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; +import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY; + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = FIRMWARE_TABLE_NAME) +public class FirmwareInfoEntity extends BaseSqlEntity implements SearchTextEntity { + + @Column(name = FIRMWARE_TENANT_ID_COLUMN) + private UUID tenantId; + + @Column(name = FIRMWARE_TITLE_COLUMN) + private String title; + + @Column(name = FIRMWARE_FILE_NAME_COLUMN) + private String fileName; + + @Column(name = FIRMWARE_CONTENT_TYPE_COLUMN) + private String contentType; + + @Column(name = SEARCH_TEXT_PROPERTY) + private String searchText; + + public FirmwareInfoEntity() { + super(); + } + + public FirmwareInfoEntity(FirmwareInfo firmware) { + this.createdTime = firmware.getCreatedTime(); + this.setUuid(firmware.getUuidId()); + this.tenantId = firmware.getTenantId().getId(); + this.title = firmware.getTitle(); + this.fileName = firmware.getFileName(); + this.contentType = firmware.getContentType(); + } + + @Override + public String getSearchTextSource() { + return title; + } + + @Override + public void setSearchText(String searchText) { + this.searchText = searchText; + } + + @Override + public FirmwareInfo toData() { + FirmwareInfo firmware = new FirmwareInfo(new FirmwareId(id)); + firmware.setCreatedTime(createdTime); + firmware.setTenantId(new TenantId(tenantId)); + firmware.setTitle(title); + firmware.setFileName(fileName); + firmware.setContentType(contentType); + 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 new file mode 100644 index 0000000000..dd4a53fe71 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareInfoRepository.java @@ -0,0 +1,34 @@ +/** + * Copyright © 2016-2021 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.dao.sql.firmware; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +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, '%'))") + Page findAllByTenantId(@Param("tenantId") UUID tenantId, + @Param("searchText") String searchText, + Pageable pageable); +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareRepository.java new file mode 100644 index 0000000000..a969507798 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/FirmwareRepository.java @@ -0,0 +1,24 @@ +/** + * Copyright © 2016-2021 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.dao.sql.firmware; + +import org.springframework.data.repository.CrudRepository; +import org.thingsboard.server.dao.model.sql.FirmwareEntity; + +import java.util.UUID; + +public interface FirmwareRepository extends CrudRepository { +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareDao.java new file mode 100644 index 0000000000..44b956c298 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareDao.java @@ -0,0 +1,46 @@ +/** + * Copyright © 2016-2021 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.dao.sql.firmware; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.dao.firmware.FirmwareDao; +import org.thingsboard.server.dao.model.sql.FirmwareEntity; +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; + +import java.util.UUID; + +@Slf4j +@Component +public class JpaFirmwareDao extends JpaAbstractSearchTextDao implements FirmwareDao { + + @Autowired + private FirmwareRepository firmwareRepository; + + @Override + protected Class getEntityClass() { + return FirmwareEntity.class; + } + + @Override + protected CrudRepository getCrudRepository() { + return firmwareRepository; + } + +} 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 new file mode 100644 index 0000000000..ae61c9ac4f --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/firmware/JpaFirmwareInfoDao.java @@ -0,0 +1,59 @@ +/** + * Copyright © 2016-2021 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.dao.sql.firmware; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.FirmwareInfo; +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.DaoUtil; +import org.thingsboard.server.dao.firmware.FirmwareInfoDao; +import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity; +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; + +import java.util.Objects; +import java.util.UUID; + +@Slf4j +@Component +public class JpaFirmwareInfoDao extends JpaAbstractSearchTextDao implements FirmwareInfoDao { + + @Autowired + private FirmwareInfoRepository firmwareInfoRepository; + + @Override + protected Class getEntityClass() { + return FirmwareInfoEntity.class; + } + + @Override + protected CrudRepository getCrudRepository() { + return firmwareInfoRepository; + } + + @Override + public PageData findFirmwareInfoByTenantId(TenantId tenantId, PageLink pageLink) { + return DaoUtil.toPageData(firmwareInfoRepository + .findAllByTenantId( + tenantId.getId(), + Objects.toString(pageLink.getTextSearch(), ""), + DaoUtil.toPageable(pageLink))); + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java index 488192eb13..c5587d36b2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/resource/TbResourceRepository.java @@ -48,8 +48,6 @@ public interface TbResourceRepository extends CrudRepository implements Comparator { @Override public int compare(D o1, D o2) { @@ -192,7 +196,7 @@ public abstract class AbstractServiceTest { @Bean public AuditLogLevelFilter auditLogLevelFilter() { - Map mask = new HashMap<>(); + Map mask = new HashMap<>(); for (EntityType entityType : EntityType.values()) { mask.put(entityType.name().toLowerCase(), AuditLogLevelMask.RW.name()); } 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 new file mode 100644 index 0000000000..b5383a1809 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseFirmwareServiceTest.java @@ -0,0 +1,271 @@ +/** + * Copyright © 2016-2021 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.dao.service; + +import com.datastax.oss.driver.api.core.uuid.Uuids; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.Firmware; +import org.thingsboard.server.common.data.FirmwareInfo; +import org.thingsboard.server.common.data.Tenant; +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.exception.DataValidationException; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public abstract class BaseFirmwareServiceTest extends AbstractServiceTest { + + public static final String TITLE = "My firmware"; + private static final String FILE_NAME = "filename.txt"; + private static final String CONTENT_TYPE = "text/plain"; + private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{0}); + + private IdComparator idComparator = new IdComparator<>(); + + private TenantId tenantId; + + @Before + public void before() { + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + Tenant savedTenant = tenantService.saveTenant(tenant); + Assert.assertNotNull(savedTenant); + tenantId = savedTenant.getId(); + } + + @After + public void after() { + tenantService.deleteTenant(tenantId); + } + + @Test + public void testSaveFirmware() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + Firmware savedFirmware = firmwareService.saveFirmware(firmware); + + Assert.assertNotNull(savedFirmware); + Assert.assertNotNull(savedFirmware.getId()); + Assert.assertTrue(savedFirmware.getCreatedTime() > 0); + Assert.assertEquals(firmware.getTenantId(), savedFirmware.getTenantId()); + Assert.assertEquals(firmware.getTitle(), savedFirmware.getTitle()); + Assert.assertEquals(firmware.getFileName(), savedFirmware.getFileName()); + Assert.assertEquals(firmware.getContentType(), savedFirmware.getContentType()); + Assert.assertEquals(firmware.getData(), savedFirmware.getData()); + + savedFirmware.setTitle("My new firmware"); + firmwareService.saveFirmware(savedFirmware); + + Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); + Assert.assertEquals(foundFirmware.getTitle(), savedFirmware.getTitle()); + + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + } + + @Test(expected = DataValidationException.class) + public void testSaveFirmwareWithEmptyTenant() { + Firmware firmware = new Firmware(); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + firmwareService.saveFirmware(firmware); + } + + @Test(expected = DataValidationException.class) + public void testSaveFirmwareWithEmptyTitle() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + firmwareService.saveFirmware(firmware); + } + + @Test(expected = DataValidationException.class) + public void testSaveFirmwareWithEmptyFileName() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + firmwareService.saveFirmware(firmware); + } + + @Test(expected = DataValidationException.class) + public void testSaveFirmwareWithEmptyContentType() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setData(DATA); + firmwareService.saveFirmware(firmware); + } + + @Test(expected = DataValidationException.class) + public void testSaveFirmwareWithEmptyData() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmwareService.saveFirmware(firmware); + } + + @Test(expected = DataValidationException.class) + public void testSaveFirmwareWithInvalidTenant() { + Firmware firmware = new Firmware(); + firmware.setTenantId(new TenantId(Uuids.timeBased())); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + firmwareService.saveFirmware(firmware); + } + + + + @Test(expected = DataValidationException.class) + public void testDeleteFirmwareWithReferenceByDevice() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + Firmware savedFirmware = firmwareService.saveFirmware(firmware); + + Device device = new Device(); + device.setTenantId(tenantId); + device.setName("My device"); + device.setType("default"); + device.setFirmwareId(savedFirmware.getId()); + Device savedDevice = deviceService.saveDevice(device); + + try { + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + } finally { + deviceService.deleteDevice(tenantId, savedDevice.getId()); + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + } + } + + @Test(expected = DataValidationException.class) + public void testDeleteFirmwareWithReferenceByDeviceProfile() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + Firmware savedFirmware = firmwareService.saveFirmware(firmware); + + DeviceProfile deviceProfile = this.createDeviceProfile(tenantId, "Device Profile"); + deviceProfile.setFirmwareId(savedFirmware.getId()); + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile); + + try { + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + } finally { + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId()); + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + } + } + + @Test + public void testFindFirmwareById() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + Firmware savedFirmware = firmwareService.saveFirmware(firmware); + + Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); + Assert.assertNotNull(foundFirmware); + Assert.assertEquals(savedFirmware, foundFirmware); + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + } + + @Test + public void testDeleteFirmware() { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + Firmware savedFirmware = firmwareService.saveFirmware(firmware); + + Firmware foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); + Assert.assertNotNull(foundFirmware); + firmwareService.deleteFirmware(tenantId, savedFirmware.getId()); + foundFirmware = firmwareService.findFirmwareById(tenantId, savedFirmware.getId()); + Assert.assertNull(foundFirmware); + } + + @Test + public void testFindTenantFirmwaresByTenantId() { + List firmwares = new ArrayList<>(); + for (int i = 0; i < 165; i++) { + Firmware firmware = new Firmware(); + firmware.setTenantId(tenantId); + firmware.setTitle(TITLE); + firmware.setFileName(FILE_NAME); + firmware.setContentType(CONTENT_TYPE); + firmware.setData(DATA); + firmwares.add(new FirmwareInfo(firmwareService.saveFirmware(firmware))); + } + + List loadedFirmwares = new ArrayList<>(); + PageLink pageLink = new PageLink(16); + PageData pageData; + do { + pageData = firmwareService.findTenantFirmwaresByTenantId(tenantId, 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()); + } + +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/sql/FirmwareServiceSqlTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/sql/FirmwareServiceSqlTest.java new file mode 100644 index 0000000000..a89414e3a2 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/sql/FirmwareServiceSqlTest.java @@ -0,0 +1,23 @@ +/** + * Copyright © 2016-2021 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.dao.service.sql; + +import org.thingsboard.server.dao.service.BaseFirmwareServiceTest; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +public class FirmwareServiceSqlTest extends BaseFirmwareServiceTest { +} diff --git a/dao/src/test/resources/sql/hsql/drop-all-tables.sql b/dao/src/test/resources/sql/hsql/drop-all-tables.sql index a548ceec30..8297553ea6 100644 --- a/dao/src/test/resources/sql/hsql/drop-all-tables.sql +++ b/dao/src/test/resources/sql/hsql/drop-all-tables.sql @@ -29,4 +29,5 @@ DROP TABLE IF EXISTS oauth2_client_registration_info; DROP TABLE IF EXISTS oauth2_client_registration_template; DROP TABLE IF EXISTS api_usage_state; DROP TABLE IF EXISTS resource; +DROP TABLE IF EXISTS firmware; DROP FUNCTION IF EXISTS to_uuid; diff --git a/dao/src/test/resources/sql/psql/drop-all-tables.sql b/dao/src/test/resources/sql/psql/drop-all-tables.sql index 333ce03fba..fbc0c76391 100644 --- a/dao/src/test/resources/sql/psql/drop-all-tables.sql +++ b/dao/src/test/resources/sql/psql/drop-all-tables.sql @@ -30,3 +30,4 @@ DROP TABLE IF EXISTS oauth2_client_registration_info; DROP TABLE IF EXISTS oauth2_client_registration_template; DROP TABLE IF EXISTS api_usage_state; DROP TABLE IF EXISTS resource; +DROP TABLE IF EXISTS firmware; diff --git a/dao/src/test/resources/sql/timescale/drop-all-tables.sql b/dao/src/test/resources/sql/timescale/drop-all-tables.sql index 211cebb2ad..950d3b2722 100644 --- a/dao/src/test/resources/sql/timescale/drop-all-tables.sql +++ b/dao/src/test/resources/sql/timescale/drop-all-tables.sql @@ -28,4 +28,6 @@ DROP TABLE IF EXISTS tb_schema_settings; DROP TABLE IF EXISTS oauth2_client_registration; DROP TABLE IF EXISTS oauth2_client_registration_info; DROP TABLE IF EXISTS oauth2_client_registration_template; -DROP TABLE IF EXISTS api_usage_state; \ No newline at end of file +DROP TABLE IF EXISTS api_usage_state; +DROP TABLE IF EXISTS resource; +DROP TABLE IF EXISTS firmware; \ No newline at end of file