Commit 4443fbcb278ceab577f794891029a6c592961819

Authored by Andrii Shvaika
1 parent 05d944e5

Refactoring of Save Device With Credentials

@@ -177,49 +177,44 @@ public class ControllerConstants { @@ -177,49 +177,44 @@ public class ControllerConstants {
177 " \"eventType\":\"DEBUG_RULE_CHAIN\",\n" + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END; 177 " \"eventType\":\"DEBUG_RULE_CHAIN\",\n" + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;
178 178
179 protected static final String IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION = "A Boolean value representing the Server SecurityInfo for future Bootstrap client mode settings. Values: 'true' for Bootstrap Server; 'false' for Lwm2m Server. "; 179 protected static final String IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION = "A Boolean value representing the Server SecurityInfo for future Bootstrap client mode settings. Values: 'true' for Bootstrap Server; 'false' for Lwm2m Server. ";
  180 +
180 protected static final String DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION = 181 protected static final String DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION =
181 - " {\n\"class org.thingsboard.server.common.data.Device\":{\n" +  
182 - " \"id\": \"null\",\n" +  
183 - " \"createdTime\":0,\n" +  
184 - " \"additionalInfo\":\"null\",\n" +  
185 - " \"tenantId\":\"null\",\n" +  
186 - " \"customerId\":\"null\",\n" +  
187 - " \"name\":\"LwRpk00000000\",\n" +  
188 - " \"type\":\"lwm2mProfileRpk\",\n" +  
189 - " \"label\":\"null\",\"" +  
190 - " \"deviceProfileId\":\"null\",\n" +  
191 - " \"deviceData\":\"null\",\n" +  
192 - " \"firmwareId\":\"null\",\n" +  
193 - " \"softwareId\":\"null\"\n" +  
194 - " },\n" +  
195 - " \"class org.thingsboard.server.common.data.security.DeviceCredentials\":{\n" +  
196 - " \"class_DeviceCredentials1\":{\n" +  
197 - " \"id\":\"null\",\n" +  
198 - " \"createdTime\":0,\n" +  
199 - " \"deviceId\":\"null|',\n" +  
200 - " \"credentialsType\":\"LWM2M_CREDENTIALS\",\n" +  
201 - " \"credentialsId\":\"LwRpk00000000\",\n" +  
202 - " \"credentialsValue\":{\n" +  
203 - " \"client\":{\n" +  
204 - " \"endpoint\":\"LwRpk00000000\",\n" +  
205 - " \"securityConfigClientMode\":\"RPK\",\n" +  
206 - " \"key\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\"\n" +  
207 - " },\n" +  
208 - " \"bootstrap\":{\n" +  
209 - " \"bootstrapServer\":{\n" +  
210 - " \"securityMode\":\"RPK\",\n" +  
211 - " \"clientPublicKeyOrId\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\",\n" +  
212 - " \"clientSecretKey\":\"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd9GAx7yZW37autew5KZykn4IgRpge/tZSjnudnZJnMahRANCAARQQHE2X9Fxgk2byaT3ULJVeggmJE5gOVdxJKorp7lsMfA5bhmI3aU2ddqXIXQnHDwxsDK2cMwRFfICNrlUQx5V\"" +  
213 - " },\n" +  
214 - " \"lwm2mServer\":{\n" +  
215 - " \"securityMode\":\"RPK\",\n" +  
216 - " \"clientPublicKeyOrId\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\",\n" +  
217 - " \"clientSecretKey\":\"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd9GAx7yZW37autew5KZykn4IgRpge/tZSjnudnZJnMahRANCAARQQHE2X9Fxgk2byaT3ULJVeggmJE5gOVdxJKorp7lsMfA5bhmI3aU2ddqXIXQnHDwxsDK2cMwRFfICNrlUQx5V\"\n" +  
218 - " }\n" +  
219 - " }\n" +  
220 - " }\n" +  
221 - " }\n" +  
222 - "}"; 182 + "{\n" +
  183 + " \"device\": {\n" +
  184 + " \"name\": \"LwRpk00000000\",\n" +
  185 + " \"type\": \"lwm2mProfileRpk\"\n" +
  186 + " },\n" +
  187 + " \"credentials\": {\n" +
  188 + " \"id\": \"null\",\n" +
  189 + " \"createdTime\": 0,\n" +
  190 + " \"deviceId\": \"null\",\n" +
  191 + " \"credentialsType\": \"LWM2M_CREDENTIALS\",\n" +
  192 + " \"credentialsId\": \"LwRpk00000000\",\n" +
  193 + " \"credentialsValue\": {\n" +
  194 + " \"client\": {\n" +
  195 + " \"endpoint\": \"LwRpk00000000\",\n" +
  196 + " \"securityConfigClientMode\": \"RPK\",\n" +
  197 + " \"key\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\"\n" +
  198 + " },\n" +
  199 + " \"bootstrap\": {\n" +
  200 + " \"bootstrapServer\": {\n" +
  201 + " \"securityMode\": \"RPK\",\n" +
  202 + " \"clientPublicKeyOrId\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\",\n" +
  203 + " \"clientSecretKey\": \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd9GAx7yZW37autew5KZykn4IgRpge/tZSjnudnZJnMahRANCAARQQHE2X9Fxgk2byaT3ULJVeggmJE5gOVdxJKorp7lsMfA5bhmI3aU2ddqXIXQnHDwxsDK2cMwRFfICNrlUQx5V\"\n" +
  204 + " },\n" +
  205 + " \"lwm2mServer\": {\n" +
  206 + " \"securityMode\": \"RPK\",\n" +
  207 + " \"clientPublicKeyOrId\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\",\n" +
  208 + " \"clientSecretKey\": \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd9GAx7yZW37autew5KZykn4IgRpge/tZSjnudnZJnMahRANCAARQQHE2X9Fxgk2byaT3ULJVeggmJE5gOVdxJKorp7lsMfA5bhmI3aU2ddqXIXQnHDwxsDK2cMwRFfICNrlUQx5V\"\n" +
  209 + " }\n" +
  210 + " }\n" +
  211 + " }\n" +
  212 + " }\n" +
  213 + "}";
  214 +
  215 + protected static final String DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN =
  216 + MARKDOWN_CODE_BLOCK_START + DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION + MARKDOWN_CODE_BLOCK_END;
  217 +
223 218
224 protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE + 219 protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE +
225 "Provides a hint about the data type of the entity field that is defined in the filter key. " + 220 "Provides a hint about the data type of the entity field that is defined in the filter key. " +
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import com.fasterxml.jackson.databind.ObjectMapper;
18 import com.google.common.util.concurrent.FutureCallback; 19 import com.google.common.util.concurrent.FutureCallback;
19 import com.google.common.util.concurrent.Futures; 20 import com.google.common.util.concurrent.Futures;
20 import com.google.common.util.concurrent.ListenableFuture; 21 import com.google.common.util.concurrent.ListenableFuture;
@@ -46,6 +47,7 @@ import org.thingsboard.server.common.data.Device; @@ -46,6 +47,7 @@ import org.thingsboard.server.common.data.Device;
46 import org.thingsboard.server.common.data.DeviceInfo; 47 import org.thingsboard.server.common.data.DeviceInfo;
47 import org.thingsboard.server.common.data.EntitySubtype; 48 import org.thingsboard.server.common.data.EntitySubtype;
48 import org.thingsboard.server.common.data.EntityType; 49 import org.thingsboard.server.common.data.EntityType;
  50 +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
49 import org.thingsboard.server.common.data.Tenant; 51 import org.thingsboard.server.common.data.Tenant;
50 import org.thingsboard.server.common.data.audit.ActionType; 52 import org.thingsboard.server.common.data.audit.ActionType;
51 import org.thingsboard.server.common.data.device.DeviceSearchQuery; 53 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
@@ -83,6 +85,7 @@ import javax.annotation.Nullable; @@ -83,6 +85,7 @@ import javax.annotation.Nullable;
83 import java.io.IOException; 85 import java.io.IOException;
84 import java.util.ArrayList; 86 import java.util.ArrayList;
85 import java.util.List; 87 import java.util.List;
  88 +import java.util.Map;
86 import java.util.UUID; 89 import java.util.UUID;
87 import java.util.stream.Collectors; 90 import java.util.stream.Collectors;
88 91
@@ -96,6 +99,8 @@ import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFI @@ -96,6 +99,8 @@ import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFI
96 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES; 99 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES;
97 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TEXT_SEARCH_DESCRIPTION; 100 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TEXT_SEARCH_DESCRIPTION;
98 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TYPE_DESCRIPTION; 101 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TYPE_DESCRIPTION;
  102 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION;
  103 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN;
99 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION; 104 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
100 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION; 105 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
101 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION; 106 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION;
@@ -198,7 +203,37 @@ public class DeviceController extends BaseController { @@ -198,7 +203,37 @@ public class DeviceController extends BaseController {
198 null, created ? ActionType.ADDED : ActionType.UPDATED, e); 203 null, created ? ActionType.ADDED : ActionType.UPDATED, e);
199 throw handleException(e); 204 throw handleException(e);
200 } 205 }
  206 + }
  207 +
  208 + @ApiOperation(value = "Create Device (saveDevice) with credentials ",
  209 + notes = "Create or update the Device. When creating device, platform generates Device Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  210 + "Requires to provide the Device Credentials object as well. Useful to create device and credentials in one request. " +
  211 + "You may find the example of LwM2M device and RPK credentials below: \n\n" +
  212 + DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN +
  213 + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
  214 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  215 + @RequestMapping(value = "/device-with-credentials", method = RequestMethod.POST)
  216 + @ResponseBody
  217 + public Device saveDeviceWithCredentials(@ApiParam(value = "The JSON object with device and credentials. See method description above for example.")
  218 + @RequestBody SaveDeviceWithCredentialsRequest deviceAndCredentials) throws ThingsboardException {
  219 + Device device = checkNotNull(deviceAndCredentials.getDevice());
  220 + DeviceCredentials credentials = checkNotNull(deviceAndCredentials.getCredentials());
  221 + try {
  222 + device.setTenantId(getCurrentUser().getTenantId());
  223 + checkEntity(device.getId(), device, Resource.DEVICE);
  224 + Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials);
  225 + checkNotNull(savedDevice);
  226 + tbClusterService.onDeviceUpdated(savedDevice, device);
  227 + logEntityAction(savedDevice.getId(), savedDevice,
  228 + savedDevice.getCustomerId(),
  229 + device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
201 230
  231 + return savedDevice;
  232 + } catch (Exception e) {
  233 + logEntityAction(emptyId(EntityType.DEVICE), device,
  234 + null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
  235 + throw handleException(e);
  236 + }
202 } 237 }
203 238
204 private void onDeviceCreatedOrUpdated(Device savedDevice, Device oldDevice, boolean updated, SecurityUser user) { 239 private void onDeviceCreatedOrUpdated(Device savedDevice, Device oldDevice, boolean updated, SecurityUser user) {
@@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
19 import io.swagger.annotations.ApiOperation; 19 import io.swagger.annotations.ApiOperation;
20 import io.swagger.annotations.ApiParam; 20 import io.swagger.annotations.ApiParam;
21 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
  22 +import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.security.access.prepost.PreAuthorize; 23 import org.springframework.security.access.prepost.PreAuthorize;
23 import org.springframework.web.bind.annotation.PathVariable; 24 import org.springframework.web.bind.annotation.PathVariable;
24 import org.springframework.web.bind.annotation.RequestBody; 25 import org.springframework.web.bind.annotation.RequestBody;
@@ -28,6 +29,7 @@ import org.springframework.web.bind.annotation.ResponseBody; @@ -28,6 +29,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
28 import org.springframework.web.bind.annotation.RestController; 29 import org.springframework.web.bind.annotation.RestController;
29 import org.thingsboard.server.common.data.Device; 30 import org.thingsboard.server.common.data.Device;
30 import org.thingsboard.server.common.data.EntityType; 31 import org.thingsboard.server.common.data.EntityType;
  32 +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
31 import org.thingsboard.server.common.data.audit.ActionType; 33 import org.thingsboard.server.common.data.audit.ActionType;
32 import org.thingsboard.server.common.data.exception.ThingsboardException; 34 import org.thingsboard.server.common.data.exception.ThingsboardException;
33 import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; 35 import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig;
@@ -46,6 +48,10 @@ import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CU @@ -46,6 +48,10 @@ import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CU
46 @TbCoreComponent 48 @TbCoreComponent
47 @RequestMapping("/api") 49 @RequestMapping("/api")
48 public class Lwm2mController extends BaseController { 50 public class Lwm2mController extends BaseController {
  51 +
  52 + @Autowired
  53 + private DeviceController deviceController;
  54 +
49 public static final String IS_BOOTSTRAP_SERVER = "isBootstrapServer"; 55 public static final String IS_BOOTSTRAP_SERVER = "isBootstrapServer";
50 56
51 57
@@ -66,41 +72,14 @@ public class Lwm2mController extends BaseController { @@ -66,41 +72,14 @@ public class Lwm2mController extends BaseController {
66 } 72 }
67 } 73 }
68 74
69 - @ApiOperation(value = "Create Device (saveDevice) with credentials ",  
70 - notes = "\nCreate new Device with credentials (example with security mode: RPK\n" +  
71 - "\nRequestBody is the Map<Class<?>, Object>:\n" +  
72 - "\nThe first param of this map: Device\n"+  
73 - "\n-- key1 = \"class org.thingsboard.server.common.data.Device\" - value1 = \"new Device()\"\n" +  
74 - "\nThe second param of this map: Device credentials\n" +  
75 - "\n-- key2 = \"class org.thingsboard.server.common.data.security.DeviceCredentials\" - value2 = \"new DeviceCredentials()\"\n" +  
76 - "\n- Example of the RequestBody with security mode: RPK:\n" +  
77 - "\n- " + DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION + "\n" +  
78 - "\nWhen creating new device, platform generates Device Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address).\n" +  
79 - "\nAfter creating new device Device DeviceCredentials is added to new Device."  
80 - + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) 75 + @ApiOperation(hidden = true, value = "Save device with credentials (Deprecated)")
81 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 76 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
82 @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST) 77 @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST)
83 @ResponseBody 78 @ResponseBody
84 - public Device saveDeviceWithCredentials(@ApiParam(value = DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION)  
85 - @RequestBody(required = false) Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException { 79 + public Device saveDeviceWithCredentials(@RequestBody Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException {
86 ObjectMapper mapper = new ObjectMapper(); 80 ObjectMapper mapper = new ObjectMapper();
87 Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class)); 81 Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class));
88 DeviceCredentials credentials = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class)); 82 DeviceCredentials credentials = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class));
89 - try {  
90 - device.setTenantId(getCurrentUser().getTenantId());  
91 - checkEntity(device.getId(), device, Resource.DEVICE);  
92 - Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials);  
93 - checkNotNull(savedDevice);  
94 - tbClusterService.onDeviceUpdated(savedDevice, device);  
95 - logEntityAction(savedDevice.getId(), savedDevice,  
96 - savedDevice.getCustomerId(),  
97 - device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);  
98 -  
99 - return savedDevice;  
100 - } catch (Exception e) {  
101 - logEntityAction(emptyId(EntityType.DEVICE), device,  
102 - null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);  
103 - throw handleException(e);  
104 - } 83 + return deviceController.saveDeviceWithCredentials(new SaveDeviceWithCredentialsRequest(device, credentials));
105 } 84 }
106 } 85 }
  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;
  17 +
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
  20 +import lombok.Data;
  21 +import org.thingsboard.server.common.data.security.DeviceCredentials;
  22 +
  23 +@ApiModel
  24 +@Data
  25 +public class SaveDeviceWithCredentialsRequest {
  26 +
  27 + @ApiModelProperty(position = 1, value = "The JSON with device entity.", required = true)
  28 + private final Device device;
  29 + @ApiModelProperty(position = 2, value = "The JSON with credentials entity.", required = true)
  30 + private final DeviceCredentials credentials;
  31 +
  32 +}
@@ -22,23 +22,23 @@ import lombok.Data; @@ -22,23 +22,23 @@ import lombok.Data;
22 @ApiModel 22 @ApiModel
23 @Data 23 @Data
24 public class ServerSecurityConfig { 24 public class ServerSecurityConfig {
25 - @ApiModelProperty(position = 1, value = "Is Bootstrap Server.", example = "true", readOnly = true) 25 + @ApiModelProperty(position = 1, value = "Is Bootstrap Server", example = "true", readOnly = true)
26 boolean bootstrapServerIs = true; 26 boolean bootstrapServerIs = true;
27 - @ApiModelProperty(position = 2, value = "Host No Security.", example = "0.0.0.0", readOnly = true) 27 + @ApiModelProperty(position = 2, value = "Host for 'No Security' mode", example = "0.0.0.0", readOnly = true)
28 String host; 28 String host;
29 - @ApiModelProperty(position = 3, value = "Port No Security.", example = "5687", readOnly = true) 29 + @ApiModelProperty(position = 3, value = "Port for 'No Security' mode", example = "5687", readOnly = true)
30 Integer port; 30 Integer port;
31 - @ApiModelProperty(position = 4, value = "Host Security.", example = "0.0.0.0", readOnly = true) 31 + @ApiModelProperty(position = 4, value = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", readOnly = true)
32 String securityHost; 32 String securityHost;
33 - @ApiModelProperty(position = 5, value = "Port Security.", example = "5688", readOnly = true) 33 + @ApiModelProperty(position = 5, value = "Port for 'Security' mode (DTLS)", example = "5688", readOnly = true)
34 Integer securityPort; 34 Integer securityPort;
35 - @ApiModelProperty(position = 5, value = "Server short Id.", example = "111", readOnly = true) 35 + @ApiModelProperty(position = 5, value = "Server short Id", example = "111", readOnly = true)
36 Integer serverId = 111; 36 Integer serverId = 111;
37 - @ApiModelProperty(position = 7, value = "Client Hold Off Time.", example = "1", readOnly = true) 37 + @ApiModelProperty(position = 7, value = "Client Hold Off Time", example = "1", readOnly = true)
38 Integer clientHoldOffTime = 1; 38 Integer clientHoldOffTime = 1;
39 - @ApiModelProperty(position = 8, value = "Server Public Key (formar base64).", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" + 39 + @ApiModelProperty(position = 8, value = "Server Public Key (base64 encoded)", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" +
40 "+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", readOnly = true) 40 "+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", readOnly = true)
41 String serverPublicKey; 41 String serverPublicKey;
42 - @ApiModelProperty(position = 9, value = "Bootstrap Server Account Timeout.", example = "0", readOnly = true) 42 + @ApiModelProperty(position = 9, value = "Bootstrap Server Account Timeout", example = "0", readOnly = true)
43 Integer bootstrapServerAccountTimeout = 0; 43 Integer bootstrapServerAccountTimeout = 0;
44 } 44 }
@@ -57,6 +57,7 @@ import org.thingsboard.server.common.data.EntityViewInfo; @@ -57,6 +57,7 @@ import org.thingsboard.server.common.data.EntityViewInfo;
57 import org.thingsboard.server.common.data.Event; 57 import org.thingsboard.server.common.data.Event;
58 import org.thingsboard.server.common.data.OtaPackage; 58 import org.thingsboard.server.common.data.OtaPackage;
59 import org.thingsboard.server.common.data.OtaPackageInfo; 59 import org.thingsboard.server.common.data.OtaPackageInfo;
  60 +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
60 import org.thingsboard.server.common.data.TbResource; 61 import org.thingsboard.server.common.data.TbResource;
61 import org.thingsboard.server.common.data.TbResourceInfo; 62 import org.thingsboard.server.common.data.TbResourceInfo;
62 import org.thingsboard.server.common.data.Tenant; 63 import org.thingsboard.server.common.data.Tenant;
@@ -1131,10 +1132,8 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1131,10 +1132,8 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1131 1132
1132 public Optional<Device> saveDeviceWithCredentials(Device device, DeviceCredentials credentials) { 1133 public Optional<Device> saveDeviceWithCredentials(Device device, DeviceCredentials credentials) {
1133 try { 1134 try {
1134 - Map<Class<?>, Object> deviceCredentials = new ConcurrentHashMap<>();  
1135 - deviceCredentials.put(Device.class, device);  
1136 - deviceCredentials.put(DeviceCredentials.class, credentials);  
1137 - ResponseEntity<Device> deviceOpt = restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class); 1135 + SaveDeviceWithCredentialsRequest request = new SaveDeviceWithCredentialsRequest(device, credentials);
  1136 + ResponseEntity<Device> deviceOpt = restTemplate.postForEntity(baseURL + "/api/device-with-credentials", request, Device.class);
1138 return Optional.ofNullable(deviceOpt.getBody()); 1137 return Optional.ofNullable(deviceOpt.getBody());
1139 } catch (HttpClientErrorException exception) { 1138 } catch (HttpClientErrorException exception) {
1140 if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { 1139 if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
@@ -1145,7 +1144,6 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1145,7 +1144,6 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1145 } 1144 }
1146 } 1145 }
1147 1146
1148 -  
1149 public PageData<Device> getTenantDevices(String type, PageLink pageLink) { 1147 public PageData<Device> getTenantDevices(String type, PageLink pageLink) {
1150 Map<String, String> params = new HashMap<>(); 1148 Map<String, String> params = new HashMap<>();
1151 params.put("type", type); 1149 params.put("type", type);