Commit 05d944e5bd727f837fc00c3a4821125b2feda1a8

Authored by Andrii Shvaika
2 parents 34ecde2c e84fbdf6

Merge remote-tracking branch 'origin/lwm2m_controller_swagger'

@@ -176,6 +176,51 @@ public class ControllerConstants { @@ -176,6 +176,51 @@ public class ControllerConstants {
176 protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{\n" + 176 protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{\n" +
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. ";
  180 + 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 + "}";
  223 +
179 protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE + 224 protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE +
180 "Provides a hint about the data type of the entity field that is defined in the filter key. " + 225 "Provides a hint about the data type of the entity field that is defined in the filter key. " +
181 "The value type impacts the list of possible operations that you may use in the corresponding predicate. For example, you may use 'STARTS_WITH' or 'END_WITH', but you can't use 'GREATER_OR_EQUAL' for string values." + 226 "The value type impacts the list of possible operations that you may use in the corresponding predicate. For example, you may use 'STARTS_WITH' or 'END_WITH', but you can't use 'GREATER_OR_EQUAL' for string values." +
@@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
  19 +import io.swagger.annotations.ApiOperation;
  20 +import io.swagger.annotations.ApiParam;
19 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
20 import org.springframework.security.access.prepost.PreAuthorize; 22 import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.PathVariable; 23 import org.springframework.web.bind.annotation.PathVariable;
@@ -35,16 +37,28 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -35,16 +37,28 @@ import org.thingsboard.server.service.security.permission.Resource;
35 37
36 import java.util.Map; 38 import java.util.Map;
37 39
  40 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION;
  41 +import static org.thingsboard.server.controller.ControllerConstants.IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION;
  42 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  43 +
38 @Slf4j 44 @Slf4j
39 @RestController 45 @RestController
40 @TbCoreComponent 46 @TbCoreComponent
41 @RequestMapping("/api") 47 @RequestMapping("/api")
42 public class Lwm2mController extends BaseController { 48 public class Lwm2mController extends BaseController {
  49 + public static final String IS_BOOTSTRAP_SERVER = "isBootstrapServer";
  50 +
43 51
  52 + @ApiOperation(value = "Get Lwm2m Bootstrap SecurityInfo (getLwm2mBootstrapSecurityInfo)",
  53 + notes = "Get the Lwm2m Bootstrap SecurityInfo object (of the current server) based on the provided isBootstrapServer parameter. If isBootstrapServer == true, get the parameters of the current Bootstrap Server. If isBootstrapServer == false, get the parameters of the current Lwm2m Server. Used for client settings when starting the client in Bootstrap mode. " +
  54 + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  55 + produces = "application/json")
44 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 56 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
45 @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET) 57 @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET)
46 @ResponseBody 58 @ResponseBody
47 - public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("isBootstrapServer") boolean bootstrapServer) throws ThingsboardException { 59 + public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(
  60 + @ApiParam(value = IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION)
  61 + @PathVariable(IS_BOOTSTRAP_SERVER) boolean bootstrapServer) throws ThingsboardException {
48 try { 62 try {
49 return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(bootstrapServer); 63 return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(bootstrapServer);
50 } catch (Exception e) { 64 } catch (Exception e) {
@@ -52,13 +66,26 @@ public class Lwm2mController extends BaseController { @@ -52,13 +66,26 @@ public class Lwm2mController extends BaseController {
52 } 66 }
53 } 67 }
54 68
  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)
55 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 81 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
56 @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST) 82 @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST)
57 @ResponseBody 83 @ResponseBody
58 - public Device saveDeviceWithCredentials(@RequestBody (required=false) Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException { 84 + public Device saveDeviceWithCredentials(@ApiParam(value = DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION)
  85 + @RequestBody(required = false) Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException {
59 ObjectMapper mapper = new ObjectMapper(); 86 ObjectMapper mapper = new ObjectMapper();
60 Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class)); 87 Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class));
61 - DeviceCredentials credentials = checkNotNull(mapper.convertValue( deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class)); 88 + DeviceCredentials credentials = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class));
62 try { 89 try {
63 device.setTenantId(getCurrentUser().getTenantId()); 90 device.setTenantId(getCurrentUser().getTenantId());
64 checkEntity(device.getId(), device, Resource.DEVICE); 91 checkEntity(device.getId(), device, Resource.DEVICE);
@@ -15,17 +15,30 @@ @@ -15,17 +15,30 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.lwm2m; 16 package org.thingsboard.server.common.data.lwm2m;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 21
  22 +@ApiModel
20 @Data 23 @Data
21 public class ServerSecurityConfig { 24 public class ServerSecurityConfig {
  25 + @ApiModelProperty(position = 1, value = "Is Bootstrap Server.", example = "true", readOnly = true)
  26 + boolean bootstrapServerIs = true;
  27 + @ApiModelProperty(position = 2, value = "Host No Security.", example = "0.0.0.0", readOnly = true)
22 String host; 28 String host;
23 - String securityHost; 29 + @ApiModelProperty(position = 3, value = "Port No Security.", example = "5687", readOnly = true)
24 Integer port; 30 Integer port;
  31 + @ApiModelProperty(position = 4, value = "Host Security.", example = "0.0.0.0", readOnly = true)
  32 + String securityHost;
  33 + @ApiModelProperty(position = 5, value = "Port Security.", example = "5688", readOnly = true)
25 Integer securityPort; 34 Integer securityPort;
26 - String serverPublicKey;  
27 - boolean bootstrapServerIs = true;  
28 - Integer clientHoldOffTime = 1; 35 + @ApiModelProperty(position = 5, value = "Server short Id.", example = "111", readOnly = true)
29 Integer serverId = 111; 36 Integer serverId = 111;
  37 + @ApiModelProperty(position = 7, value = "Client Hold Off Time.", example = "1", readOnly = true)
  38 + Integer clientHoldOffTime = 1;
  39 + @ApiModelProperty(position = 8, value = "Server Public Key (formar base64).", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" +
  40 + "+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", readOnly = true)
  41 + String serverPublicKey;
  42 + @ApiModelProperty(position = 9, value = "Bootstrap Server Account Timeout.", example = "0", readOnly = true)
30 Integer bootstrapServerAccountTimeout = 0; 43 Integer bootstrapServerAccountTimeout = 0;
31 } 44 }
@@ -1134,7 +1134,6 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1134,7 +1134,6 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1134 Map<Class<?>, Object> deviceCredentials = new ConcurrentHashMap<>(); 1134 Map<Class<?>, Object> deviceCredentials = new ConcurrentHashMap<>();
1135 deviceCredentials.put(Device.class, device); 1135 deviceCredentials.put(Device.class, device);
1136 deviceCredentials.put(DeviceCredentials.class, credentials); 1136 deviceCredentials.put(DeviceCredentials.class, credentials);
1137 -// return restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class).getBody();  
1138 ResponseEntity<Device> deviceOpt = restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class); 1137 ResponseEntity<Device> deviceOpt = restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class);
1139 return Optional.ofNullable(deviceOpt.getBody()); 1138 return Optional.ofNullable(deviceOpt.getBody());
1140 } catch (HttpClientErrorException exception) { 1139 } catch (HttpClientErrorException exception) {