Commit 350581028021897cf1a51ad6f5bcc2b81f5cc71d
1 parent
41e57249
Bulk import device credentials handling refactoring
Showing
8 changed files
with
65 additions
and
24 deletions
@@ -18,8 +18,6 @@ package org.thingsboard.server.service.device; | @@ -18,8 +18,6 @@ package org.thingsboard.server.service.device; | ||
18 | import com.fasterxml.jackson.databind.node.BooleanNode; | 18 | import com.fasterxml.jackson.databind.node.BooleanNode; |
19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
20 | import com.fasterxml.jackson.databind.node.TextNode; | 20 | import com.fasterxml.jackson.databind.node.TextNode; |
21 | -import com.google.gson.JsonObject; | ||
22 | -import com.google.gson.JsonPrimitive; | ||
23 | import lombok.SneakyThrows; | 21 | import lombok.SneakyThrows; |
24 | import org.apache.commons.collections.CollectionUtils; | 22 | import org.apache.commons.collections.CollectionUtils; |
25 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
@@ -39,10 +37,10 @@ import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTrans | @@ -39,10 +37,10 @@ import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTrans | ||
39 | import org.thingsboard.server.common.data.id.TenantId; | 37 | import org.thingsboard.server.common.data.id.TenantId; |
40 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 38 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
41 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 39 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
42 | -import org.thingsboard.server.common.transport.adaptor.JsonConverter; | ||
43 | import org.thingsboard.server.dao.device.DeviceCredentialsService; | 40 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
44 | import org.thingsboard.server.dao.device.DeviceProfileService; | 41 | import org.thingsboard.server.dao.device.DeviceProfileService; |
45 | import org.thingsboard.server.dao.device.DeviceService; | 42 | import org.thingsboard.server.dao.device.DeviceService; |
43 | +import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException; | ||
46 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | 44 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
47 | import org.thingsboard.server.queue.util.TbCoreComponent; | 45 | import org.thingsboard.server.queue.util.TbCoreComponent; |
48 | import org.thingsboard.server.service.action.EntityActionService; | 46 | import org.thingsboard.server.service.action.EntityActionService; |
@@ -63,8 +61,6 @@ import java.util.Set; | @@ -63,8 +61,6 @@ import java.util.Set; | ||
63 | import java.util.stream.Collectors; | 61 | import java.util.stream.Collectors; |
64 | import java.util.stream.Stream; | 62 | import java.util.stream.Stream; |
65 | 63 | ||
66 | -import static org.thingsboard.server.dao.service.Validator.validateId; | ||
67 | - | ||
68 | @Service | 64 | @Service |
69 | @TbCoreComponent | 65 | @TbCoreComponent |
70 | public class DeviceBulkImportService extends AbstractBulkImportService<Device> { | 66 | public class DeviceBulkImportService extends AbstractBulkImportService<Device> { |
@@ -104,7 +100,18 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> { | @@ -104,7 +100,18 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> { | ||
104 | if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) { | 100 | if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) { |
105 | setUpLwM2mDeviceProfile(user.getTenantId(), device); | 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 | } else { | 115 | } else { |
109 | device = deviceService.saveDevice(device); | 116 | device = deviceService.saveDevice(device); |
110 | } | 117 | } |
@@ -80,6 +80,10 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent | @@ -80,6 +80,10 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent | ||
80 | 80 | ||
81 | saveKvs(user, entity, entityData); | 81 | saveKvs(user, entity, entityData); |
82 | 82 | ||
83 | + if (importedEntityInfo.getRelatedError() != null) { | ||
84 | + throw new RuntimeException(importedEntityInfo.getRelatedError()); | ||
85 | + } | ||
86 | + | ||
83 | if (importedEntityInfo.isUpdated()) { | 87 | if (importedEntityInfo.isUpdated()) { |
84 | result.setUpdated(result.getUpdated() + 1); | 88 | result.setUpdated(result.getUpdated() + 1); |
85 | } else { | 89 | } else { |
@@ -22,4 +22,5 @@ public class ImportedEntityInfo<E> { | @@ -22,4 +22,5 @@ public class ImportedEntityInfo<E> { | ||
22 | private E entity; | 22 | private E entity; |
23 | private boolean isUpdated; | 23 | private boolean isUpdated; |
24 | private E oldEntity; | 24 | private E oldEntity; |
25 | + private String relatedError; | ||
25 | } | 26 | } |
@@ -54,6 +54,8 @@ public interface DeviceService { | @@ -54,6 +54,8 @@ public interface DeviceService { | ||
54 | 54 | ||
55 | Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials); | 55 | Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials); |
56 | 56 | ||
57 | + void createAccessTokenCredentials(Device device, String accessToken); | ||
58 | + | ||
57 | Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId); | 59 | Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId); |
58 | 60 | ||
59 | Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId); | 61 | Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId); |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.transport.adaptor; | 16 | package org.thingsboard.server.common.transport.adaptor; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.databind.JsonNode; | ||
19 | import com.google.gson.Gson; | 18 | import com.google.gson.Gson; |
20 | import com.google.gson.JsonArray; | 19 | import com.google.gson.JsonArray; |
21 | import com.google.gson.JsonElement; | 20 | import com.google.gson.JsonElement; |
@@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; | @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; | ||
37 | import org.thingsboard.server.common.msg.EncryptionUtil; | 37 | import org.thingsboard.server.common.msg.EncryptionUtil; |
38 | import org.thingsboard.server.dao.entity.AbstractEntityService; | 38 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
39 | import org.thingsboard.server.dao.exception.DataValidationException; | 39 | import org.thingsboard.server.dao.exception.DataValidationException; |
40 | +import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException; | ||
40 | import org.thingsboard.server.dao.service.DataValidator; | 41 | import org.thingsboard.server.dao.service.DataValidator; |
41 | 42 | ||
42 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE; | 43 | import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CREDENTIALS_CACHE; |
@@ -117,10 +118,10 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | @@ -117,10 +118,10 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | ||
117 | throw new IllegalArgumentException(); | 118 | throw new IllegalArgumentException(); |
118 | } | 119 | } |
119 | } catch (IllegalArgumentException e) { | 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 | if (StringUtils.isEmpty(mqttCredentials.getClientId()) && StringUtils.isEmpty(mqttCredentials.getUserName())) { | 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 | if (StringUtils.isEmpty(mqttCredentials.getClientId())) { | 126 | if (StringUtils.isEmpty(mqttCredentials.getClientId())) { |
126 | deviceCredentials.setCredentialsId(mqttCredentials.getUserName()); | 127 | deviceCredentials.setCredentialsId(mqttCredentials.getUserName()); |
@@ -155,7 +156,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | @@ -155,7 +156,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | ||
155 | throw new IllegalArgumentException(); | 156 | throw new IllegalArgumentException(); |
156 | } | 157 | } |
157 | } catch (IllegalArgumentException e) { | 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 | String credentialsId = null; | 162 | String credentialsId = null; |
@@ -183,7 +184,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | @@ -183,7 +184,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | ||
183 | break; | 184 | break; |
184 | } | 185 | } |
185 | if (credentialsId == null) { | 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 | deviceCredentials.setCredentialsId(credentialsId); | 189 | deviceCredentials.setCredentialsId(credentialsId); |
189 | } | 190 | } |
@@ -201,38 +202,38 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | @@ -201,38 +202,38 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen | ||
201 | @Override | 202 | @Override |
202 | protected void validateCreate(TenantId tenantId, DeviceCredentials deviceCredentials) { | 203 | protected void validateCreate(TenantId tenantId, DeviceCredentials deviceCredentials) { |
203 | if (deviceCredentialsDao.findByDeviceId(tenantId, deviceCredentials.getDeviceId().getId()) != null) { | 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 | if (deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId()) != null) { | 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 | @Override | 212 | @Override |
212 | protected void validateUpdate(TenantId tenantId, DeviceCredentials deviceCredentials) { | 213 | protected void validateUpdate(TenantId tenantId, DeviceCredentials deviceCredentials) { |
213 | if (deviceCredentialsDao.findById(tenantId, deviceCredentials.getUuidId()) == null) { | 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 | DeviceCredentials existingCredentials = deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId()); | 217 | DeviceCredentials existingCredentials = deviceCredentialsDao.findByCredentialsId(tenantId, deviceCredentials.getCredentialsId()); |
217 | if (existingCredentials != null && !existingCredentials.getId().equals(deviceCredentials.getId())) { | 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 | @Override | 223 | @Override |
223 | protected void validateDataImpl(TenantId tenantId, DeviceCredentials deviceCredentials) { | 224 | protected void validateDataImpl(TenantId tenantId, DeviceCredentials deviceCredentials) { |
224 | if (deviceCredentials.getDeviceId() == null) { | 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 | if (deviceCredentials.getCredentialsType() == null) { | 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 | if (StringUtils.isEmpty(deviceCredentials.getCredentialsId())) { | 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 | Device device = deviceService.findDeviceById(tenantId, deviceCredentials.getDeviceId()); | 234 | Device device = deviceService.findDeviceById(tenantId, deviceCredentials.getDeviceId()); |
234 | if (device == null) { | 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,15 +230,20 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
230 | private Device doSaveDevice(Device device, String accessToken, boolean doValidate) { | 230 | private Device doSaveDevice(Device device, String accessToken, boolean doValidate) { |
231 | Device savedDevice = this.saveDeviceWithoutCredentials(device, doValidate); | 231 | Device savedDevice = this.saveDeviceWithoutCredentials(device, doValidate); |
232 | if (device.getId() == null) { | 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 | return savedDevice; | 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 | private Device saveDeviceWithoutCredentials(Device device, boolean doValidate) { | 247 | private Device saveDeviceWithoutCredentials(Device device, boolean doValidate) { |
243 | log.trace("Executing saveDevice [{}]", device); | 248 | log.trace("Executing saveDevice [{}]", device); |
244 | if (doValidate) { | 249 | if (doValidate) { |
dao/src/main/java/org/thingsboard/server/dao/exception/DeviceCredentialsValidationException.java
0 → 100644
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 | +} |