Commit 350581028021897cf1a51ad6f5bcc2b81f5cc71d

Authored by Viacheslav Klimov
1 parent 41e57249

Bulk import device credentials handling refactoring

... ... @@ -18,8 +18,6 @@ package org.thingsboard.server.service.device;
18 18 import com.fasterxml.jackson.databind.node.BooleanNode;
19 19 import com.fasterxml.jackson.databind.node.ObjectNode;
20 20 import com.fasterxml.jackson.databind.node.TextNode;
21   -import com.google.gson.JsonObject;
22   -import com.google.gson.JsonPrimitive;
23 21 import lombok.SneakyThrows;
24 22 import org.apache.commons.collections.CollectionUtils;
25 23 import org.springframework.stereotype.Service;
... ... @@ -39,10 +37,10 @@ import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTrans
39 37 import org.thingsboard.server.common.data.id.TenantId;
40 38 import org.thingsboard.server.common.data.security.DeviceCredentials;
41 39 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
42   -import org.thingsboard.server.common.transport.adaptor.JsonConverter;
43 40 import org.thingsboard.server.dao.device.DeviceCredentialsService;
44 41 import org.thingsboard.server.dao.device.DeviceProfileService;
45 42 import org.thingsboard.server.dao.device.DeviceService;
  43 +import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException;
46 44 import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
47 45 import org.thingsboard.server.queue.util.TbCoreComponent;
48 46 import org.thingsboard.server.service.action.EntityActionService;
... ... @@ -63,8 +61,6 @@ import java.util.Set;
63 61 import java.util.stream.Collectors;
64 62 import java.util.stream.Stream;
65 63
66   -import static org.thingsboard.server.dao.service.Validator.validateId;
67   -
68 64 @Service
69 65 @TbCoreComponent
70 66 public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
... ... @@ -104,7 +100,18 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
104 100 if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) {
105 101 setUpLwM2mDeviceProfile(user.getTenantId(), device);
106 102 }
107   - device = deviceService.saveDeviceWithCredentials(device, deviceCredentials);
  103 + try {
  104 + device = deviceService.saveDeviceWithCredentials(device, deviceCredentials);
  105 + } catch (DeviceCredentialsValidationException e) {
  106 + if (deviceCredentials.getId() == null) {
  107 + device.setId(deviceCredentials.getDeviceId());
  108 + importedEntityInfo.setRelatedError("Failed to create " + deviceCredentials.getCredentialsType() + " credentials: "
  109 + + e.getMessage() + ". Falling back to access token creds");
  110 + deviceService.createAccessTokenCredentials(device, null);
  111 + } else {
  112 + importedEntityInfo.setRelatedError("Failed to update credentials: " + e.getMessage());
  113 + }
  114 + }
108 115 } else {
109 116 device = deviceService.saveDevice(device);
110 117 }
... ...
... ... @@ -80,6 +80,10 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent
80 80
81 81 saveKvs(user, entity, entityData);
82 82
  83 + if (importedEntityInfo.getRelatedError() != null) {
  84 + throw new RuntimeException(importedEntityInfo.getRelatedError());
  85 + }
  86 +
83 87 if (importedEntityInfo.isUpdated()) {
84 88 result.setUpdated(result.getUpdated() + 1);
85 89 } else {
... ...
... ... @@ -22,4 +22,5 @@ public class ImportedEntityInfo<E> {
22 22 private E entity;
23 23 private boolean isUpdated;
24 24 private E oldEntity;
  25 + private String relatedError;
25 26 }
... ...
... ... @@ -54,6 +54,8 @@ public interface DeviceService {
54 54
55 55 Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials);
56 56
  57 + void createAccessTokenCredentials(Device device, String accessToken);
  58 +
57 59 Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId);
58 60
59 61 Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId);
... ...
... ... @@ -15,7 +15,6 @@
15 15 */
16 16 package org.thingsboard.server.common.transport.adaptor;
17 17
18   -import com.fasterxml.jackson.databind.JsonNode;
19 18 import com.google.gson.Gson;
20 19 import com.google.gson.JsonArray;
21 20 import com.google.gson.JsonElement;
... ...
... ... @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials;
37 37 import org.thingsboard.server.common.msg.EncryptionUtil;
38 38 import org.thingsboard.server.dao.entity.AbstractEntityService;
39 39 import org.thingsboard.server.dao.exception.DataValidationException;
  40 +import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException;
40 41 import org.thingsboard.server.dao.service.DataValidator;
41 42
42 43 import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE;
... ... @@ -117,10 +118,10 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen
117 118 throw new IllegalArgumentException();
118 119 }
119 120 } catch (IllegalArgumentException e) {
120   - throw new DataValidationException("Invalid credentials body for simple mqtt credentials!");
  121 + throw new DeviceCredentialsValidationException("Invalid credentials body for simple mqtt credentials!");
121 122 }
122 123 if (StringUtils.isEmpty(mqttCredentials.getClientId()) && StringUtils.isEmpty(mqttCredentials.getUserName())) {
123   - throw new DataValidationException("Both mqtt client id and user name are empty!");
  124 + throw new DeviceCredentialsValidationException("Both mqtt client id and user name are empty!");
124 125 }
125 126 if (StringUtils.isEmpty(mqttCredentials.getClientId())) {
126 127 deviceCredentials.setCredentialsId(mqttCredentials.getUserName());
... ... @@ -155,7 +156,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen
155 156 throw new IllegalArgumentException();
156 157 }
157 158 } catch (IllegalArgumentException e) {
158   - throw new DataValidationException("Invalid credentials body for LwM2M credentials!");
  159 + throw new DeviceCredentialsValidationException("Invalid credentials body for LwM2M credentials!");
159 160 }
160 161
161 162 String credentialsId = null;
... ... @@ -183,7 +184,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen
183 184 break;
184 185 }
185 186 if (credentialsId == null) {
186   - throw new DataValidationException("Invalid credentials body for LwM2M credentials!");
  187 + throw new DeviceCredentialsValidationException("Invalid credentials body for LwM2M credentials!");
187 188 }
188 189 deviceCredentials.setCredentialsId(credentialsId);
189 190 }
... ... @@ -201,38 +202,38 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen
201 202 @Override
202 203 protected void validateCreate(TenantId tenantId, DeviceCredentials deviceCredentials) {
203 204 if (deviceCredentialsDao.findByDeviceId(tenantId, deviceCredentials.getDeviceId().getId()) != null) {
204   - throw new DataValidationException("Credentials for this device are already specified!");
  205 + throw new DeviceCredentialsValidationException("Credentials for this device are already specified!");
205 206 }
206 207 if (deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId()) != null) {
207   - throw new DataValidationException("Device credentials are already assigned to another device!");
  208 + throw new DeviceCredentialsValidationException("Device credentials are already assigned to another device!");
208 209 }
209 210 }
210 211
211 212 @Override
212 213 protected void validateUpdate(TenantId tenantId, DeviceCredentials deviceCredentials) {
213 214 if (deviceCredentialsDao.findById(tenantId, deviceCredentials.getUuidId()) == null) {
214   - throw new DataValidationException("Unable to update non-existent device credentials!");
  215 + throw new DeviceCredentialsValidationException("Unable to update non-existent device credentials!");
215 216 }
216 217 DeviceCredentials existingCredentials = deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId());
217 218 if (existingCredentials != null && !existingCredentials.getId().equals(deviceCredentials.getId())) {
218   - throw new DataValidationException("Device credentials are already assigned to another device!");
  219 + throw new DeviceCredentialsValidationException("Device credentials are already assigned to another device!");
219 220 }
220 221 }
221 222
222 223 @Override
223 224 protected void validateDataImpl(TenantId tenantId, DeviceCredentials deviceCredentials) {
224 225 if (deviceCredentials.getDeviceId() == null) {
225   - throw new DataValidationException("Device credentials should be assigned to device!");
  226 + throw new DeviceCredentialsValidationException("Device credentials should be assigned to device!");
226 227 }
227 228 if (deviceCredentials.getCredentialsType() == null) {
228   - throw new DataValidationException("Device credentials type should be specified!");
  229 + throw new DeviceCredentialsValidationException("Device credentials type should be specified!");
229 230 }
230 231 if (StringUtils.isEmpty(deviceCredentials.getCredentialsId())) {
231   - throw new DataValidationException("Device credentials id should be specified!");
  232 + throw new DeviceCredentialsValidationException("Device credentials id should be specified!");
232 233 }
233 234 Device device = deviceService.findDeviceById(tenantId, deviceCredentials.getDeviceId());
234 235 if (device == null) {
235   - throw new DataValidationException("Can't assign device credentials to non-existent device!");
  236 + throw new DeviceCredentialsValidationException("Can't assign device credentials to non-existent device!");
236 237 }
237 238 }
238 239 };
... ...
... ... @@ -230,15 +230,20 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
230 230 private Device doSaveDevice(Device device, String accessToken, boolean doValidate) {
231 231 Device savedDevice = this.saveDeviceWithoutCredentials(device, doValidate);
232 232 if (device.getId() == null) {
233   - DeviceCredentials deviceCredentials = new DeviceCredentials();
234   - deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId()));
235   - deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
236   - deviceCredentials.setCredentialsId(!StringUtils.isEmpty(accessToken) ? accessToken : RandomStringUtils.randomAlphanumeric(20));
237   - deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
  233 + createAccessTokenCredentials(savedDevice, accessToken);
238 234 }
239 235 return savedDevice;
240 236 }
241 237
  238 + @Override
  239 + public void createAccessTokenCredentials(Device device, String accessToken) {
  240 + DeviceCredentials deviceCredentials = new DeviceCredentials();
  241 + deviceCredentials.setDeviceId(new DeviceId(device.getUuidId()));
  242 + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
  243 + deviceCredentials.setCredentialsId(!StringUtils.isEmpty(accessToken) ? accessToken : RandomStringUtils.randomAlphanumeric(20));
  244 + deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
  245 + }
  246 +
242 247 private Device saveDeviceWithoutCredentials(Device device, boolean doValidate) {
243 248 log.trace("Executing saveDevice [{}]", device);
244 249 if (doValidate) {
... ...
  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.dao.exception;
  17 +
  18 +public class DeviceCredentialsValidationException extends DataValidationException {
  19 + public DeviceCredentialsValidationException(String message) {
  20 + super(message);
  21 + }
  22 +}
... ...