Commit 7a4d302c858a98c5958c0ef516cbaadcc24c6c87

Authored by zbeacon
1 parent 8a5a4f09

Changes according to comments from @ashvayka

... ... @@ -15,7 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.controller;
17 17
18   -import com.google.common.hash.Hashing;
19 18 import lombok.extern.slf4j.Slf4j;
20 19 import org.apache.commons.lang3.StringUtils;
21 20 import org.springframework.core.io.ByteArrayResource;
... ... @@ -33,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile;
33 32 import org.thingsboard.server.common.data.Firmware;
34 33 import org.thingsboard.server.common.data.FirmwareInfo;
35 34 import org.thingsboard.server.common.data.exception.ThingsboardException;
  35 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
36 36 import org.thingsboard.server.common.data.id.FirmwareId;
37 37 import org.thingsboard.server.common.data.page.PageData;
38 38 import org.thingsboard.server.common.data.page.PageLink;
... ... @@ -49,6 +49,7 @@ import java.nio.ByteBuffer;
49 49 public class FirmwareController extends BaseController {
50 50
51 51 public static final String FIRMWARE_ID = "firmwareId";
  52 + public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm";
52 53
53 54 @PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')")
54 55 @RequestMapping(value = "/firmware/{firmwareId}/download", method = RequestMethod.GET)
... ... @@ -115,9 +116,10 @@ public class FirmwareController extends BaseController {
115 116 @ResponseBody
116 117 public Firmware saveFirmwareData(@PathVariable(FIRMWARE_ID) String strFirmwareId,
117 118 @RequestParam(required = false) String checksum,
118   - @RequestParam() String checksumAlgorithm,
  119 + @RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,
119 120 @RequestBody MultipartFile file) throws ThingsboardException {
120 121 checkParameter(FIRMWARE_ID, strFirmwareId);
  122 + checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr);
121 123 try {
122 124 FirmwareId firmwareId = new FirmwareId(toUUID(strFirmwareId));
123 125 FirmwareInfo info = checkFirmwareInfoId(firmwareId, Operation.READ);
... ... @@ -129,6 +131,8 @@ public class FirmwareController extends BaseController {
129 131 firmware.setVersion(info.getVersion());
130 132 firmware.setAdditionalInfo(info.getAdditionalInfo());
131 133
  134 + ChecksumAlgorithm checksumAlgorithm = ChecksumAlgorithm.valueOf(checksumAlgorithmStr.toUpperCase());
  135 +
132 136 ByteBuffer data = ByteBuffer.wrap(file.getBytes());
133 137 if (StringUtils.isEmpty(checksum)) {
134 138 checksum = firmwareService.generateChecksum(checksumAlgorithm, data);
... ... @@ -139,7 +143,7 @@ public class FirmwareController extends BaseController {
139 143 firmware.setFileName(file.getOriginalFilename());
140 144 firmware.setContentType(file.getContentType());
141 145 firmware.setData(data);
142   - firmware.setDataSize((long) data.array().length);
  146 + firmware.setDataSize((long) data.capacity());
143 147 return firmwareService.saveFirmware(firmware);
144 148 } catch (Exception e) {
145 149 throw handleException(e);
... ...
... ... @@ -227,7 +227,7 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
227 227 attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_VERSION, firmware.getVersion())));
228 228
229 229 attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(FIRMWARE_SIZE, firmware.getDataSize())));
230   - attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm())));
  230 + attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm().name())));
231 231 attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM, firmware.getChecksum())));
232 232 telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() {
233 233 @Override
... ...
... ... @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.firmware;
17 17
18 18 import org.thingsboard.server.common.data.Firmware;
19 19 import org.thingsboard.server.common.data.FirmwareInfo;
  20 +import org.thingsboard.server.common.data.exception.ThingsboardException;
  21 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
20 22 import org.thingsboard.server.common.data.id.FirmwareId;
21 23 import org.thingsboard.server.common.data.id.TenantId;
22 24 import org.thingsboard.server.common.data.page.PageData;
... ... @@ -30,7 +32,9 @@ public interface FirmwareService {
30 32
31 33 Firmware saveFirmware(Firmware firmware);
32 34
33   - String generateChecksum(String checksumAlgorithm, ByteBuffer data);
  35 + PageData<String> getSupportedChecksumAlgorithms(PageLink pageLink);
  36 +
  37 + String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data) throws ThingsboardException;
34 38
35 39 Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId);
36 40
... ...
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data;
18 18 import lombok.Data;
19 19 import lombok.EqualsAndHashCode;
20 20 import lombok.extern.slf4j.Slf4j;
  21 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
21 22 import org.thingsboard.server.common.data.id.FirmwareId;
22 23 import org.thingsboard.server.common.data.id.TenantId;
23 24
... ... @@ -34,7 +35,7 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId>
34 35 private boolean hasData;
35 36 private String fileName;
36 37 private String contentType;
37   - private String checksumAlgorithm;
  38 + private ChecksumAlgorithm checksumAlgorithm;
38 39 private String checksum;
39 40 private Long dataSize;
40 41
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.firmware;
  17 +
  18 +public enum ChecksumAlgorithm {
  19 + MD5,
  20 + SHA256,
  21 + SHA384,
  22 + SHA512,
  23 + CRC32,
  24 + MURMUR3_32,
  25 + MURMUR3_128
  26 +}
... ...
... ... @@ -26,6 +26,9 @@ import org.springframework.stereotype.Service;
26 26 import org.thingsboard.server.common.data.Firmware;
27 27 import org.thingsboard.server.common.data.FirmwareInfo;
28 28 import org.thingsboard.server.common.data.Tenant;
  29 +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
  30 +import org.thingsboard.server.common.data.exception.ThingsboardException;
  31 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
29 32 import org.thingsboard.server.common.data.id.FirmwareId;
30 33 import org.thingsboard.server.common.data.id.TenantId;
31 34 import org.thingsboard.server.common.data.page.PageData;
... ... @@ -35,8 +38,13 @@ import org.thingsboard.server.dao.service.DataValidator;
35 38 import org.thingsboard.server.dao.service.PaginatedRemover;
36 39 import org.thingsboard.server.dao.tenant.TenantDao;
37 40
  41 +import java.lang.reflect.InvocationTargetException;
  42 +import java.lang.reflect.Method;
38 43 import java.nio.ByteBuffer;
  44 +import java.util.ArrayList;
  45 +import java.util.Arrays;
39 46 import java.util.Collections;
  47 +import java.util.List;
40 48 import java.util.Optional;
41 49
42 50 import static org.thingsboard.server.common.data.CacheConstants.FIRMWARE_CACHE;
... ... @@ -102,7 +110,7 @@ public class BaseFirmwareService implements FirmwareService {
102 110 }
103 111
104 112 @Override
105   - public String generateChecksum(String checksumAlgorithm, ByteBuffer data) {
  113 + public String generateChecksum(ChecksumAlgorithm checksumAlgorithm, ByteBuffer data) throws ThingsboardException {
106 114
107 115 if (data == null || !data.hasArray() || data.array().length == 0) {
108 116 throw new DataValidationException("Firmware data should be specified!");
... ... @@ -110,22 +118,43 @@ public class BaseFirmwareService implements FirmwareService {
110 118
111 119 HashFunction hashFunction;
112 120 switch (checksumAlgorithm) {
113   - case "sha256":
  121 + case MD5:
  122 + hashFunction = Hashing.md5();
  123 + break;
  124 + case SHA256:
114 125 hashFunction = Hashing.sha256();
115 126 break;
116   - case "md5":
117   - hashFunction = Hashing.md5();
  127 + case SHA384:
  128 + hashFunction = Hashing.sha384();
118 129 break;
119   - case "crc32":
  130 + case SHA512:
  131 + hashFunction = Hashing.sha512();
  132 + break;
  133 + case CRC32:
120 134 hashFunction = Hashing.crc32();
121 135 break;
  136 + case MURMUR3_32:
  137 + hashFunction = Hashing.murmur3_32();
  138 + break;
  139 + case MURMUR3_128:
  140 + hashFunction = Hashing.murmur3_128();
  141 + break;
122 142 default:
123 143 throw new DataValidationException("Unknown checksum algorithm!");
124 144 }
125   -
126 145 return hashFunction.hashBytes(data.array()).toString();
127 146 }
128 147
  148 + @Override
  149 + public PageData<String> getSupportedChecksumAlgorithms(PageLink pageLink) {
  150 + List<String> methodNames = new ArrayList<>();
  151 + Method[] hashingMethods = Hashing.class.getMethods();
  152 + Arrays.stream(hashingMethods).forEach(method -> {
  153 + methodNames.add(method.getName());
  154 + });
  155 + return new PageData<>(methodNames, 1, methodNames.size(), false);
  156 + }
  157 +
129 158
130 159 @Override
131 160 public Firmware findFirmwareById(TenantId tenantId, FirmwareId firmwareId) {
... ... @@ -150,7 +179,8 @@ public class BaseFirmwareService implements FirmwareService {
150 179 }
151 180
152 181 @Override
153   - public PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId, boolean hasData, PageLink pageLink) {
  182 + public PageData<FirmwareInfo> findTenantFirmwaresByTenantIdAndHasData(TenantId tenantId,
  183 + boolean hasData, PageLink pageLink) {
154 184 log.trace("Executing findTenantFirmwaresByTenantIdAndHasData, tenantId [{}], hasData [{}] pageLink [{}]", tenantId, hasData, pageLink);
155 185 validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
156 186 validatePageLink(pageLink);
... ... @@ -243,14 +273,20 @@ public class BaseFirmwareService implements FirmwareService {
243 273 throw new DataValidationException("Firmware content type should be specified!");
244 274 }
245 275
246   - if (StringUtils.isEmpty(firmware.getChecksumAlgorithm())) {
  276 + if (firmware.getChecksumAlgorithm() == null) {
247 277 throw new DataValidationException("Firmware checksum algorithm should be specified!");
248 278 }
249 279 if (StringUtils.isEmpty(firmware.getChecksum())) {
250 280 throw new DataValidationException("Firmware checksum should be specified!");
251 281 }
252 282
253   - String currentChecksum = generateChecksum(firmware.getChecksumAlgorithm(), firmware.getData());
  283 + String currentChecksum;
  284 +
  285 + try {
  286 + currentChecksum = generateChecksum(firmware.getChecksumAlgorithm(), firmware.getData());
  287 + } catch (ThingsboardException e) {
  288 + throw new DataValidationException(e.getMessage());
  289 + }
254 290
255 291 if (!currentChecksum.equals(firmware.getChecksum())) {
256 292 throw new DataValidationException("Wrong firmware file!");
... ...
... ... @@ -21,6 +21,7 @@ import lombok.EqualsAndHashCode;
21 21 import org.hibernate.annotations.Type;
22 22 import org.hibernate.annotations.TypeDef;
23 23 import org.thingsboard.server.common.data.Firmware;
  24 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
24 25 import org.thingsboard.server.common.data.id.FirmwareId;
25 26 import org.thingsboard.server.common.data.id.TenantId;
26 27 import org.thingsboard.server.dao.model.BaseSqlEntity;
... ... @@ -30,6 +31,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
30 31
31 32 import javax.persistence.Column;
32 33 import javax.persistence.Entity;
  34 +import javax.persistence.EnumType;
  35 +import javax.persistence.Enumerated;
33 36 import javax.persistence.Table;
34 37 import java.nio.ByteBuffer;
35 38 import java.util.UUID;
... ... @@ -68,8 +71,9 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
68 71 @Column(name = FIRMWARE_CONTENT_TYPE_COLUMN)
69 72 private String contentType;
70 73
  74 + @Enumerated(EnumType.STRING)
71 75 @Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN)
72   - private String checksumAlgorithm;
  76 + private ChecksumAlgorithm checksumAlgorithm;
73 77
74 78 @Column(name = FIRMWARE_CHECKSUM_COLUMN)
75 79 private String checksum;
... ...
... ... @@ -22,6 +22,7 @@ import org.hibernate.annotations.Type;
22 22 import org.hibernate.annotations.TypeDef;
23 23 import org.thingsboard.common.util.JacksonUtil;
24 24 import org.thingsboard.server.common.data.FirmwareInfo;
  25 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
25 26 import org.thingsboard.server.common.data.id.FirmwareId;
26 27 import org.thingsboard.server.common.data.id.TenantId;
27 28 import org.thingsboard.server.dao.model.BaseSqlEntity;
... ... @@ -31,6 +32,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
31 32
32 33 import javax.persistence.Column;
33 34 import javax.persistence.Entity;
  35 +import javax.persistence.EnumType;
  36 +import javax.persistence.Enumerated;
34 37 import javax.persistence.Table;
35 38 import javax.persistence.Transient;
36 39 import java.util.UUID;
... ... @@ -70,8 +73,9 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
70 73 @Column(name = FIRMWARE_CONTENT_TYPE_COLUMN)
71 74 private String contentType;
72 75
  76 + @Enumerated(EnumType.STRING)
73 77 @Column(name = FIRMWARE_CHECKSUM_ALGORITHM_COLUMN)
74   - private String checksumAlgorithm;
  78 + private ChecksumAlgorithm checksumAlgorithm;
75 79
76 80 @Column(name = FIRMWARE_CHECKSUM_COLUMN)
77 81 private String checksum;
... ... @@ -108,7 +112,7 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
108 112 }
109 113
110 114 public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, String title, String version,
111   - String fileName, String contentType, String checksumAlgorithm, String checksum, Long dataSize,
  115 + String fileName, String contentType, ChecksumAlgorithm checksumAlgorithm, String checksum, Long dataSize,
112 116 Object additionalInfo, boolean hasData) {
113 117 this.id = id;
114 118 this.createdTime = createdTime;
... ...
... ... @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.DeviceProfileInfo;
30 30 import org.thingsboard.server.common.data.DeviceTransportType;
31 31 import org.thingsboard.server.common.data.Firmware;
32 32 import org.thingsboard.server.common.data.Tenant;
  33 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
33 34 import org.thingsboard.server.common.data.id.TenantId;
34 35 import org.thingsboard.server.common.data.page.PageData;
35 36 import org.thingsboard.server.common.data.page.PageLink;
... ... @@ -101,7 +102,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
101 102 firmware.setVersion("v1.0");
102 103 firmware.setFileName("test.txt");
103 104 firmware.setContentType("text/plain");
104   - firmware.setChecksumAlgorithm("sha256");
  105 + firmware.setChecksumAlgorithm(ChecksumAlgorithm.SHA256);
105 106 firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
106 107 firmware.setData(ByteBuffer.wrap(new byte[]{1}));
107 108 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
... ...
... ... @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.EntitySubtype;
28 28 import org.thingsboard.server.common.data.Firmware;
29 29 import org.thingsboard.server.common.data.Tenant;
30 30 import org.thingsboard.server.common.data.TenantProfile;
  31 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
31 32 import org.thingsboard.server.common.data.id.CustomerId;
32 33 import org.thingsboard.server.common.data.id.TenantId;
33 34 import org.thingsboard.server.common.data.page.PageData;
... ... @@ -187,7 +188,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
187 188 firmware.setVersion("v1.0");
188 189 firmware.setFileName("test.txt");
189 190 firmware.setContentType("text/plain");
190   - firmware.setChecksumAlgorithm("sha256");
  191 + firmware.setChecksumAlgorithm(ChecksumAlgorithm.SHA256);
191 192 firmware.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
192 193 firmware.setData(ByteBuffer.wrap(new byte[]{1}));
193 194 Firmware savedFirmware = firmwareService.saveFirmware(firmware);
... ...
... ... @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
26 26 import org.thingsboard.server.common.data.Firmware;
27 27 import org.thingsboard.server.common.data.FirmwareInfo;
28 28 import org.thingsboard.server.common.data.Tenant;
  29 +import org.thingsboard.server.common.data.firmware.ChecksumAlgorithm;
29 30 import org.thingsboard.server.common.data.id.TenantId;
30 31 import org.thingsboard.server.common.data.page.PageData;
31 32 import org.thingsboard.server.common.data.page.PageLink;
... ... @@ -42,7 +43,7 @@ public abstract class BaseFirmwareServiceTest extends AbstractServiceTest {
42 43 private static final String FILE_NAME = "filename.txt";
43 44 private static final String VERSION = "v1.0";
44 45 private static final String CONTENT_TYPE = "text/plain";
45   - private static final String CHECKSUM_ALGORITHM = "sha256";
  46 + private static final ChecksumAlgorithm CHECKSUM_ALGORITHM = ChecksumAlgorithm.SHA256;
46 47 private static final String CHECKSUM = "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a";
47 48 private static final ByteBuffer DATA = ByteBuffer.wrap(new byte[]{1});
48 49
... ...
... ... @@ -19,16 +19,24 @@ import { TenantId } from '@shared/models/id/tenant-id';
19 19 import { FirmwareId } from '@shared/models/id/firmware-id';
20 20
21 21 export enum ChecksumAlgorithm {
22   - MD5 = 'md5',
23   - SHA256 = 'sha256',
24   - CRC32 = 'crc32'
  22 + MD5 = 'MD5',
  23 + SHA256 = 'SHA256',
  24 + SHA384 = 'SHA384',
  25 + SHA512 = 'SHA512',
  26 + CRC32 = 'CRC32',
  27 + MURMUR3_32 = 'MURMUR3_32',
  28 + MURMUR3_128 = 'MURMUR3_128'
25 29 }
26 30
27 31 export const ChecksumAlgorithmTranslationMap = new Map<ChecksumAlgorithm, string>(
28 32 [
29 33 [ChecksumAlgorithm.MD5, 'MD5'],
30 34 [ChecksumAlgorithm.SHA256, 'SHA-256'],
31   - [ChecksumAlgorithm.CRC32, 'CRC-32']
  35 + [ChecksumAlgorithm.SHA384, 'SHA-384'],
  36 + [ChecksumAlgorithm.SHA512, 'SHA-512'],
  37 + [ChecksumAlgorithm.CRC32, 'CRC-32'],
  38 + [ChecksumAlgorithm.MURMUR3_32, 'MURMUR3-32'],
  39 + [ChecksumAlgorithm.MURMUR3_128, 'MURMUR3-128']
32 40 ]
33 41 );
34 42
... ...