Commit d4ee2fde2f6313d035ffa7f59d3d1cfb767d03a9

Authored by Andrew Shvayka
Committed by GitHub
2 parents 7f1f2987 fbdb7bf2

Merge pull request #5425 from thingsboard/feature/swagger

Optimize Swagger Constants
Showing 42 changed files with 2119 additions and 943 deletions

Too many changes to show.

To preserve performance only 42 of 59 files are displayed.

@@ -41,12 +41,13 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -41,12 +41,13 @@ import org.thingsboard.server.service.security.permission.Resource;
41 import org.thingsboard.server.service.security.system.SystemSecurityService; 41 import org.thingsboard.server.service.security.system.SystemSecurityService;
42 import org.thingsboard.server.service.update.UpdateService; 42 import org.thingsboard.server.service.update.UpdateService;
43 43
  44 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
  45 +
44 @RestController 46 @RestController
45 @TbCoreComponent 47 @TbCoreComponent
46 @RequestMapping("/api/admin") 48 @RequestMapping("/api/admin")
47 public class AdminController extends BaseController { 49 public class AdminController extends BaseController {
48 50
49 - public static final String SYS_ADMIN_AUTHORITY_ONLY = " Available for users with System Administrator ('SYS_ADMIN') authority only.";  
50 @Autowired 51 @Autowired
51 private MailService mailService; 52 private MailService mailService;
52 53
@@ -63,7 +64,7 @@ public class AdminController extends BaseController { @@ -63,7 +64,7 @@ public class AdminController extends BaseController {
63 private UpdateService updateService; 64 private UpdateService updateService;
64 65
65 @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)", 66 @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)",
66 - notes = "Get the Administration Settings object using specified string key. Referencing non-existing key will cause an error." + SYS_ADMIN_AUTHORITY_ONLY) 67 + notes = "Get the Administration Settings object using specified string key. Referencing non-existing key will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
67 @PreAuthorize("hasAuthority('SYS_ADMIN')") 68 @PreAuthorize("hasAuthority('SYS_ADMIN')")
68 @RequestMapping(value = "/settings/{key}", method = RequestMethod.GET) 69 @RequestMapping(value = "/settings/{key}", method = RequestMethod.GET)
69 @ResponseBody 70 @ResponseBody
@@ -86,7 +87,7 @@ public class AdminController extends BaseController { @@ -86,7 +87,7 @@ public class AdminController extends BaseController {
86 @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)", 87 @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)",
87 notes = "Creates or Updates the Administration Settings. Platform generates random Administration Settings Id during settings creation. " + 88 notes = "Creates or Updates the Administration Settings. Platform generates random Administration Settings Id during settings creation. " +
88 "The Administration Settings Id will be present in the response. Specify the Administration Settings Id when you would like to update the Administration Settings. " + 89 "The Administration Settings Id will be present in the response. Specify the Administration Settings Id when you would like to update the Administration Settings. " +
89 - "Referencing non-existing Administration Settings Id will cause an error." + SYS_ADMIN_AUTHORITY_ONLY) 90 + "Referencing non-existing Administration Settings Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
90 @PreAuthorize("hasAuthority('SYS_ADMIN')") 91 @PreAuthorize("hasAuthority('SYS_ADMIN')")
91 @RequestMapping(value = "/settings", method = RequestMethod.POST) 92 @RequestMapping(value = "/settings", method = RequestMethod.POST)
92 @ResponseBody 93 @ResponseBody
@@ -109,7 +110,7 @@ public class AdminController extends BaseController { @@ -109,7 +110,7 @@ public class AdminController extends BaseController {
109 } 110 }
110 111
111 @ApiOperation(value = "Get the Security Settings object", 112 @ApiOperation(value = "Get the Security Settings object",
112 - notes = "Get the Security Settings object that contains password policy, etc." + SYS_ADMIN_AUTHORITY_ONLY) 113 + notes = "Get the Security Settings object that contains password policy, etc." + SYSTEM_AUTHORITY_PARAGRAPH)
113 @PreAuthorize("hasAuthority('SYS_ADMIN')") 114 @PreAuthorize("hasAuthority('SYS_ADMIN')")
114 @RequestMapping(value = "/securitySettings", method = RequestMethod.GET) 115 @RequestMapping(value = "/securitySettings", method = RequestMethod.GET)
115 @ResponseBody 116 @ResponseBody
@@ -123,7 +124,7 @@ public class AdminController extends BaseController { @@ -123,7 +124,7 @@ public class AdminController extends BaseController {
123 } 124 }
124 125
125 @ApiOperation(value = "Update Security Settings (saveSecuritySettings)", 126 @ApiOperation(value = "Update Security Settings (saveSecuritySettings)",
126 - notes = "Updates the Security Settings object that contains password policy, etc." + SYS_ADMIN_AUTHORITY_ONLY) 127 + notes = "Updates the Security Settings object that contains password policy, etc." + SYSTEM_AUTHORITY_PARAGRAPH)
127 @PreAuthorize("hasAuthority('SYS_ADMIN')") 128 @PreAuthorize("hasAuthority('SYS_ADMIN')")
128 @RequestMapping(value = "/securitySettings", method = RequestMethod.POST) 129 @RequestMapping(value = "/securitySettings", method = RequestMethod.POST)
129 @ResponseBody 130 @ResponseBody
@@ -141,7 +142,7 @@ public class AdminController extends BaseController { @@ -141,7 +142,7 @@ public class AdminController extends BaseController {
141 142
142 @ApiOperation(value = "Send test email (sendTestMail)", 143 @ApiOperation(value = "Send test email (sendTestMail)",
143 notes = "Attempts to send test email to the System Administrator User using Mail Settings provided as a parameter. " + 144 notes = "Attempts to send test email to the System Administrator User using Mail Settings provided as a parameter. " +
144 - "You may change the 'To' email in the user profile of the System Administrator. " + SYS_ADMIN_AUTHORITY_ONLY) 145 + "You may change the 'To' email in the user profile of the System Administrator. " + SYSTEM_AUTHORITY_PARAGRAPH)
145 @PreAuthorize("hasAuthority('SYS_ADMIN')") 146 @PreAuthorize("hasAuthority('SYS_ADMIN')")
146 @RequestMapping(value = "/settings/testMail", method = RequestMethod.POST) 147 @RequestMapping(value = "/settings/testMail", method = RequestMethod.POST)
147 public void sendTestMail( 148 public void sendTestMail(
@@ -165,7 +166,7 @@ public class AdminController extends BaseController { @@ -165,7 +166,7 @@ public class AdminController extends BaseController {
165 166
166 @ApiOperation(value = "Send test sms (sendTestMail)", 167 @ApiOperation(value = "Send test sms (sendTestMail)",
167 notes = "Attempts to send test sms to the System Administrator User using SMS Settings and phone number provided as a parameters of the request. " 168 notes = "Attempts to send test sms to the System Administrator User using SMS Settings and phone number provided as a parameters of the request. "
168 - + SYS_ADMIN_AUTHORITY_ONLY) 169 + + SYSTEM_AUTHORITY_PARAGRAPH)
169 @PreAuthorize("hasAuthority('SYS_ADMIN')") 170 @PreAuthorize("hasAuthority('SYS_ADMIN')")
170 @RequestMapping(value = "/settings/testSms", method = RequestMethod.POST) 171 @RequestMapping(value = "/settings/testSms", method = RequestMethod.POST)
171 public void sendTestSms( 172 public void sendTestSms(
@@ -181,7 +182,7 @@ public class AdminController extends BaseController { @@ -181,7 +182,7 @@ public class AdminController extends BaseController {
181 182
182 @ApiOperation(value = "Check for new Platform Releases (checkUpdates)", 183 @ApiOperation(value = "Check for new Platform Releases (checkUpdates)",
183 notes = "Check notifications about new platform releases. " 184 notes = "Check notifications about new platform releases. "
184 - + SYS_ADMIN_AUTHORITY_ONLY) 185 + + SYSTEM_AUTHORITY_PARAGRAPH)
185 @PreAuthorize("hasAuthority('SYS_ADMIN')") 186 @PreAuthorize("hasAuthority('SYS_ADMIN')")
186 @RequestMapping(value = "/updates", method = RequestMethod.GET) 187 @RequestMapping(value = "/updates", method = RequestMethod.GET)
187 @ResponseBody 188 @ResponseBody
@@ -52,6 +52,21 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -52,6 +52,21 @@ import org.thingsboard.server.service.security.permission.Resource;
52 52
53 import java.util.List; 53 import java.util.List;
54 54
  55 +import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION;
  56 +import static org.thingsboard.server.controller.ControllerConstants.ALARM_INFO_DESCRIPTION;
  57 +import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES;
  58 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID;
  59 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION;
  60 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE;
  61 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_PARAM_DESCRIPTION;
  62 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  63 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  64 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  65 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  66 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  67 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  68 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  69 +
55 @RestController 70 @RestController
56 @TbCoreComponent 71 @TbCoreComponent
57 @RequestMapping("/api") 72 @RequestMapping("/api")
@@ -88,7 +103,7 @@ public class AlarmController extends BaseController { @@ -88,7 +103,7 @@ public class AlarmController extends BaseController {
88 103
89 @ApiOperation(value = "Get Alarm Info (getAlarmInfoById)", 104 @ApiOperation(value = "Get Alarm Info (getAlarmInfoById)",
90 notes = "Fetch the Alarm Info object based on the provided Alarm Id. " + 105 notes = "Fetch the Alarm Info object based on the provided Alarm Id. " +
91 - ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE) 106 + ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
92 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 107 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
93 @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET) 108 @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET)
94 @ResponseBody 109 @ResponseBody
@@ -111,7 +126,7 @@ public class AlarmController extends BaseController { @@ -111,7 +126,7 @@ public class AlarmController extends BaseController {
111 "\n\nPlatform also deduplicate the alarms based on the entity id of originator and alarm 'type'. " + 126 "\n\nPlatform also deduplicate the alarms based on the entity id of originator and alarm 'type'. " +
112 "For example, if the user or system component create the alarm with the type 'HighTemperature' for device 'Device A' the new active alarm is created. " + 127 "For example, if the user or system component create the alarm with the type 'HighTemperature' for device 'Device A' the new active alarm is created. " +
113 "If the user tries to create 'HighTemperature' alarm for the same device again, the previous alarm will be updated (the 'end_ts' will be set to current timestamp). " + 128 "If the user tries to create 'HighTemperature' alarm for the same device again, the previous alarm will be updated (the 'end_ts' will be set to current timestamp). " +
114 - "If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. " 129 + "If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
115 , produces = MediaType.APPLICATION_JSON_VALUE) 130 , produces = MediaType.APPLICATION_JSON_VALUE)
116 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 131 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
117 @RequestMapping(value = "/alarm", method = RequestMethod.POST) 132 @RequestMapping(value = "/alarm", method = RequestMethod.POST)
@@ -138,7 +153,7 @@ public class AlarmController extends BaseController { @@ -138,7 +153,7 @@ public class AlarmController extends BaseController {
138 } 153 }
139 154
140 @ApiOperation(value = "Delete Alarm (deleteAlarm)", 155 @ApiOperation(value = "Delete Alarm (deleteAlarm)",
141 - notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error.", produces = MediaType.APPLICATION_JSON_VALUE) 156 + notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
142 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 157 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
143 @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE) 158 @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE)
144 @ResponseBody 159 @ResponseBody
@@ -165,7 +180,7 @@ public class AlarmController extends BaseController { @@ -165,7 +180,7 @@ public class AlarmController extends BaseController {
165 @ApiOperation(value = "Acknowledge Alarm (ackAlarm)", 180 @ApiOperation(value = "Acknowledge Alarm (ackAlarm)",
166 notes = "Acknowledge the Alarm. " + 181 notes = "Acknowledge the Alarm. " +
167 "Once acknowledged, the 'ack_ts' field will be set to current timestamp and special rule chain event 'ALARM_ACK' will be generated. " + 182 "Once acknowledged, the 'ack_ts' field will be set to current timestamp and special rule chain event 'ALARM_ACK' will be generated. " +
168 - "Referencing non-existing Alarm Id will cause an error.", produces = MediaType.APPLICATION_JSON_VALUE) 183 + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
169 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 184 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
170 @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) 185 @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
171 @ResponseStatus(value = HttpStatus.OK) 186 @ResponseStatus(value = HttpStatus.OK)
@@ -189,7 +204,7 @@ public class AlarmController extends BaseController { @@ -189,7 +204,7 @@ public class AlarmController extends BaseController {
189 @ApiOperation(value = "Clear Alarm (clearAlarm)", 204 @ApiOperation(value = "Clear Alarm (clearAlarm)",
190 notes = "Clear the Alarm. " + 205 notes = "Clear the Alarm. " +
191 "Once cleared, the 'clear_ts' field will be set to current timestamp and special rule chain event 'ALARM_CLEAR' will be generated. " + 206 "Once cleared, the 'clear_ts' field will be set to current timestamp and special rule chain event 'ALARM_CLEAR' will be generated. " +
192 - "Referencing non-existing Alarm Id will cause an error.", produces = MediaType.APPLICATION_JSON_VALUE) 207 + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
193 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 208 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
194 @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) 209 @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST)
195 @ResponseStatus(value = HttpStatus.OK) 210 @ResponseStatus(value = HttpStatus.OK)
@@ -212,8 +227,8 @@ public class AlarmController extends BaseController { @@ -212,8 +227,8 @@ public class AlarmController extends BaseController {
212 227
213 @ApiOperation(value = "Get Alarms (getAlarms)", 228 @ApiOperation(value = "Get Alarms (getAlarms)",
214 notes = "Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + 229 notes = "Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " +
215 - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE)  
216 - @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 230 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
  231 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
217 @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) 232 @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET)
218 @ResponseBody 233 @ResponseBody
219 public PageData<AlarmInfo> getAlarms( 234 public PageData<AlarmInfo> getAlarms(
@@ -265,7 +280,7 @@ public class AlarmController extends BaseController { @@ -265,7 +280,7 @@ public class AlarmController extends BaseController {
265 "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + 280 "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " +
266 "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + 281 "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " +
267 "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + 282 "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " +
268 - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) 283 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
269 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 284 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
270 @RequestMapping(value = "/alarms", method = RequestMethod.GET) 285 @RequestMapping(value = "/alarms", method = RequestMethod.GET)
271 @ResponseBody 286 @ResponseBody
@@ -312,7 +327,7 @@ public class AlarmController extends BaseController { @@ -312,7 +327,7 @@ public class AlarmController extends BaseController {
312 327
313 @ApiOperation(value = "Get Highest Alarm Severity (getHighestAlarmSeverity)", 328 @ApiOperation(value = "Get Highest Alarm Severity (getHighestAlarmSeverity)",
314 notes = "Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). " + 329 notes = "Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). " +
315 - "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error." 330 + "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
316 , produces = MediaType.APPLICATION_JSON_VALUE) 331 , produces = MediaType.APPLICATION_JSON_VALUE)
317 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 332 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
318 @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) 333 @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET)
@@ -64,6 +64,26 @@ import java.util.ArrayList; @@ -64,6 +64,26 @@ import java.util.ArrayList;
64 import java.util.List; 64 import java.util.List;
65 import java.util.stream.Collectors; 65 import java.util.stream.Collectors;
66 66
  67 +import static org.thingsboard.server.controller.ControllerConstants.ASSET_ID_PARAM_DESCRIPTION;
  68 +import static org.thingsboard.server.controller.ControllerConstants.ASSET_INFO_DESCRIPTION;
  69 +import static org.thingsboard.server.controller.ControllerConstants.ASSET_NAME_DESCRIPTION;
  70 +import static org.thingsboard.server.controller.ControllerConstants.ASSET_SORT_PROPERTY_ALLOWABLE_VALUES;
  71 +import static org.thingsboard.server.controller.ControllerConstants.ASSET_TEXT_SEARCH_DESCRIPTION;
  72 +import static org.thingsboard.server.controller.ControllerConstants.ASSET_TYPE_DESCRIPTION;
  73 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
  74 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  75 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
  76 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION;
  77 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  78 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
  79 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  80 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  81 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  82 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  83 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  84 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  85 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  86 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
67 import static org.thingsboard.server.controller.EdgeController.EDGE_ID; 87 import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
68 import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE; 88 import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE;
69 89
@@ -80,7 +100,8 @@ public class AssetController extends BaseController { @@ -80,7 +100,8 @@ public class AssetController extends BaseController {
80 @ApiOperation(value = "Get Asset (getAssetById)", 100 @ApiOperation(value = "Get Asset (getAssetById)",
81 notes = "Fetch the Asset object based on the provided Asset Id. " + 101 notes = "Fetch the Asset object based on the provided Asset Id. " +
82 "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + 102 "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " +
83 - "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer.", produces = MediaType.APPLICATION_JSON_VALUE) 103 + "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
  104 + , produces = MediaType.APPLICATION_JSON_VALUE)
84 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 105 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
85 @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET) 106 @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET)
86 @ResponseBody 107 @ResponseBody
@@ -98,7 +119,8 @@ public class AssetController extends BaseController { @@ -98,7 +119,8 @@ public class AssetController extends BaseController {
98 @ApiOperation(value = "Get Asset Info (getAssetInfoById)", 119 @ApiOperation(value = "Get Asset Info (getAssetInfoById)",
99 notes = "Fetch the Asset Info object based on the provided Asset Id. " + 120 notes = "Fetch the Asset Info object based on the provided Asset Id. " +
100 "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + 121 "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " +
101 - "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer. " + ASSET_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE) 122 + "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer. "
  123 + + ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
102 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 124 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
103 @RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET) 125 @RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET)
104 @ResponseBody 126 @ResponseBody
@@ -117,7 +139,7 @@ public class AssetController extends BaseController { @@ -117,7 +139,7 @@ public class AssetController extends BaseController {
117 notes = "Creates or Updates the Asset. When creating asset, platform generates Asset Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) " + 139 notes = "Creates or Updates the Asset. When creating asset, platform generates Asset Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) " +
118 "The newly created Asset id will be present in the response. " + 140 "The newly created Asset id will be present in the response. " +
119 "Specify existing Asset id to update the asset. " + 141 "Specify existing Asset id to update the asset. " +
120 - "Referencing non-existing Asset Id will cause 'Not Found' error.", produces = MediaType.APPLICATION_JSON_VALUE) 142 + "Referencing non-existing Asset Id will cause 'Not Found' error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
121 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 143 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
122 @RequestMapping(value = "/asset", method = RequestMethod.POST) 144 @RequestMapping(value = "/asset", method = RequestMethod.POST)
123 @ResponseBody 145 @ResponseBody
@@ -158,7 +180,7 @@ public class AssetController extends BaseController { @@ -158,7 +180,7 @@ public class AssetController extends BaseController {
158 } 180 }
159 181
160 @ApiOperation(value = "Delete asset (deleteAsset)", 182 @ApiOperation(value = "Delete asset (deleteAsset)",
161 - notes = "Deletes the asset and all the relations (from and to the asset). Referencing non-existing asset Id will cause an error.") 183 + notes = "Deletes the asset and all the relations (from and to the asset). Referencing non-existing asset Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
162 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 184 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
163 @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.DELETE) 185 @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.DELETE)
164 @ResponseStatus(value = HttpStatus.OK) 186 @ResponseStatus(value = HttpStatus.OK)
@@ -187,7 +209,7 @@ public class AssetController extends BaseController { @@ -187,7 +209,7 @@ public class AssetController extends BaseController {
187 } 209 }
188 210
189 @ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)", 211 @ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)",
190 - notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards.", produces = MediaType.APPLICATION_JSON_VALUE) 212 + notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
191 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 213 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
192 @RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST) 214 @RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST)
193 @ResponseBody 215 @ResponseBody
@@ -223,7 +245,7 @@ public class AssetController extends BaseController { @@ -223,7 +245,7 @@ public class AssetController extends BaseController {
223 } 245 }
224 246
225 @ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)", 247 @ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)",
226 - notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards.", produces = MediaType.APPLICATION_JSON_VALUE) 248 + notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
227 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 249 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
228 @RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE) 250 @RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE)
229 @ResponseBody 251 @ResponseBody
@@ -261,7 +283,7 @@ public class AssetController extends BaseController { @@ -261,7 +283,7 @@ public class AssetController extends BaseController {
261 @ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)", 283 @ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)",
262 notes = "Asset will be available for non-authorized (not logged-in) users. " + 284 notes = "Asset will be available for non-authorized (not logged-in) users. " +
263 "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + 285 "This is useful to create dashboards that you plan to share/embed on a publicly available website. " +
264 - "However, users that are logged-in and belong to different tenant will not be able to access the asset.", produces = MediaType.APPLICATION_JSON_VALUE) 286 + "However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
265 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 287 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
266 @RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST) 288 @RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST)
267 @ResponseBody 289 @ResponseBody
@@ -290,7 +312,7 @@ public class AssetController extends BaseController { @@ -290,7 +312,7 @@ public class AssetController extends BaseController {
290 312
291 @ApiOperation(value = "Get Tenant Assets (getTenantAssets)", 313 @ApiOperation(value = "Get Tenant Assets (getTenantAssets)",
292 notes = "Returns a page of assets owned by tenant. " + 314 notes = "Returns a page of assets owned by tenant. " +
293 - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) 315 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
294 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 316 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
295 @RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) 317 @RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
296 @ResponseBody 318 @ResponseBody
@@ -322,7 +344,7 @@ public class AssetController extends BaseController { @@ -322,7 +344,7 @@ public class AssetController extends BaseController {
322 344
323 @ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)", 345 @ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)",
324 notes = "Returns a page of assets info objects owned by tenant. " + 346 notes = "Returns a page of assets info objects owned by tenant. " +
325 - PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE) 347 + PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
326 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 348 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
327 @RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 349 @RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
328 @ResponseBody 350 @ResponseBody
@@ -354,7 +376,7 @@ public class AssetController extends BaseController { @@ -354,7 +376,7 @@ public class AssetController extends BaseController {
354 376
355 @ApiOperation(value = "Get Tenant Asset (getTenantAsset)", 377 @ApiOperation(value = "Get Tenant Asset (getTenantAsset)",
356 notes = "Requested asset must be owned by tenant that the user belongs to. " + 378 notes = "Requested asset must be owned by tenant that the user belongs to. " +
357 - "Asset name is an unique property of asset. So it can be used to identify the asset.", produces = MediaType.APPLICATION_JSON_VALUE) 379 + "Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
358 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 380 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
359 @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET) 381 @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET)
360 @ResponseBody 382 @ResponseBody
@@ -42,6 +42,19 @@ import java.util.List; @@ -42,6 +42,19 @@ import java.util.List;
42 import java.util.UUID; 42 import java.util.UUID;
43 import java.util.stream.Collectors; 43 import java.util.stream.Collectors;
44 44
  45 +import static org.thingsboard.server.controller.ControllerConstants.AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES;
  46 +import static org.thingsboard.server.controller.ControllerConstants.AUDIT_LOG_TEXT_SEARCH_DESCRIPTION;
  47 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
  48 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION;
  49 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_PARAM_DESCRIPTION;
  50 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  51 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  52 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  53 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  54 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  55 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  56 +import static org.thingsboard.server.controller.ControllerConstants.USER_ID_PARAM_DESCRIPTION;
  57 +
45 @RestController 58 @RestController
46 @TbCoreComponent 59 @TbCoreComponent
47 @RequestMapping("/api") 60 @RequestMapping("/api")
@@ -60,7 +73,7 @@ public class AuditLogController extends BaseController { @@ -60,7 +73,7 @@ public class AuditLogController extends BaseController {
60 @ApiOperation(value = "Get audit logs by customer id (getAuditLogsByCustomerId)", 73 @ApiOperation(value = "Get audit logs by customer id (getAuditLogsByCustomerId)",
61 notes = "Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), " + 74 notes = "Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), " +
62 "and users actions (login, logout, etc.) that belong to this customer. " + 75 "and users actions (login, logout, etc.) that belong to this customer. " +
63 - PAGE_DATA_PARAMETERS + ADMINISTRATOR_AUTHORITY_ONLY, 76 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH,
64 produces = MediaType.APPLICATION_JSON_VALUE) 77 produces = MediaType.APPLICATION_JSON_VALUE)
65 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 78 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
66 @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET) 79 @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -98,7 +111,7 @@ public class AuditLogController extends BaseController { @@ -98,7 +111,7 @@ public class AuditLogController extends BaseController {
98 @ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)", 111 @ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)",
99 notes = "Returns a page of audit logs related to the actions of targeted user. " + 112 notes = "Returns a page of audit logs related to the actions of targeted user. " +
100 "For example, RPC call to a particular device, or alarm acknowledgment for a specific device, etc. " + 113 "For example, RPC call to a particular device, or alarm acknowledgment for a specific device, etc. " +
101 - PAGE_DATA_PARAMETERS + ADMINISTRATOR_AUTHORITY_ONLY, 114 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH,
102 produces = MediaType.APPLICATION_JSON_VALUE) 115 produces = MediaType.APPLICATION_JSON_VALUE)
103 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 116 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
104 @RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET) 117 @RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -137,7 +150,7 @@ public class AuditLogController extends BaseController { @@ -137,7 +150,7 @@ public class AuditLogController extends BaseController {
137 notes = "Returns a page of audit logs related to the actions on the targeted entity. " + 150 notes = "Returns a page of audit logs related to the actions on the targeted entity. " +
138 "Basically, this API call is used to get the full lifecycle of some specific entity. " + 151 "Basically, this API call is used to get the full lifecycle of some specific entity. " +
139 "For example to see when a device was created, updated, assigned to some customer, or even deleted from the system. " + 152 "For example to see when a device was created, updated, assigned to some customer, or even deleted from the system. " +
140 - PAGE_DATA_PARAMETERS + ADMINISTRATOR_AUTHORITY_ONLY, 153 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH,
141 produces = MediaType.APPLICATION_JSON_VALUE) 154 produces = MediaType.APPLICATION_JSON_VALUE)
142 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 155 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
143 @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET) 156 @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -177,7 +190,7 @@ public class AuditLogController extends BaseController { @@ -177,7 +190,7 @@ public class AuditLogController extends BaseController {
177 190
178 @ApiOperation(value = "Get all audit logs (getAuditLogs)", 191 @ApiOperation(value = "Get all audit logs (getAuditLogs)",
179 notes = "Returns a page of audit logs related to all entities in the scope of the current user's Tenant. " + 192 notes = "Returns a page of audit logs related to all entities in the scope of the current user's Tenant. " +
180 - PAGE_DATA_PARAMETERS + ADMINISTRATOR_AUTHORITY_ONLY, 193 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH,
181 produces = MediaType.APPLICATION_JSON_VALUE) 194 produces = MediaType.APPLICATION_JSON_VALUE)
182 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 195 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
183 @RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET) 196 @RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -147,6 +147,8 @@ import java.util.Optional; @@ -147,6 +147,8 @@ import java.util.Optional;
147 import java.util.Set; 147 import java.util.Set;
148 import java.util.UUID; 148 import java.util.UUID;
149 149
  150 +import static org.thingsboard.server.controller.ControllerConstants.DEFAULT_PAGE_SIZE;
  151 +import static org.thingsboard.server.controller.ControllerConstants.INCORRECT_TENANT_ID;
150 import static org.thingsboard.server.dao.service.Validator.validateId; 152 import static org.thingsboard.server.dao.service.Validator.validateId;
151 153
152 @Slf4j 154 @Slf4j
@@ -155,121 +157,6 @@ public abstract class BaseController { @@ -155,121 +157,6 @@ public abstract class BaseController {
155 157
156 /*Swagger UI description*/ 158 /*Swagger UI description*/
157 159
158 - public static final String CUSTOMER_ID = "customerId";  
159 - public static final String TENANT_ID = "tenantId";  
160 - public static final String DEVICE_ID = "deviceId";  
161 - public static final String RPC_ID = "rpcId";  
162 - public static final String ENTITY_ID = "entityId";  
163 - public static final String ENTITY_TYPE = "entityType";  
164 -  
165 - public static final String PAGE_DATA_PARAMETERS = "You can specify parameters to filter the results. " +  
166 - "The result is wrapped with PageData object that allows you to iterate over result set using pagination. " +  
167 - "See the 'Model' tab of the Response Class for more details. ";  
168 - public static final String DASHBOARD_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
169 - public static final String RPC_ID_PARAM_DESCRIPTION = "A string value representing the rpc id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
170 - public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
171 - public static final String DEVICE_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
172 - public static final String TENANT_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the tenant profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
173 - public static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
174 - public static final String EDGE_ID_PARAM_DESCRIPTION = "A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
175 - public static final String CUSTOMER_ID_PARAM_DESCRIPTION = "A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
176 - public static final String USER_ID_PARAM_DESCRIPTION = "A string value representing the user id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
177 - public static final String ASSET_ID_PARAM_DESCRIPTION = "A string value representing the asset id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
178 - public static final String ALARM_ID_PARAM_DESCRIPTION = "A string value representing the alarm id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
179 - public static final String ENTITY_ID_PARAM_DESCRIPTION = "A string value representing the entity id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
180 - public static final String ENTITY_TYPE_PARAM_DESCRIPTION = "A string value representing the entity type. For example, 'DEVICE'";  
181 - public static final String RULE_CHAIN_ID_PARAM_DESCRIPTION = "A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";  
182 -  
183 - protected static final String SYSTEM_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' authority.";  
184 - protected static final String SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority.";  
185 - protected static final String TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' authority.";  
186 - protected static final String TENANT_OR_USER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority.";  
187 -  
188 - protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page";  
189 - protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0";  
190 - protected static final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile";  
191 - protected static final String ASSET_TYPE_DESCRIPTION = "Asset type";  
192 - protected static final String EDGE_TYPE_DESCRIPTION = "A string value representing the edge type. For example, 'default'";  
193 - protected static final String RULE_CHAIN_TYPE_DESCRIPTION = "Rule chain type (CORE or EDGE)";  
194 -  
195 - protected static final String ASSET_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the asset name.";  
196 - protected static final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title.";  
197 - protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty.";  
198 - protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name.";  
199 - protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email.";  
200 - protected static final String TENANT_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant name.";  
201 - protected static final String TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant profile name.";  
202 - protected static final String RULE_CHAIN_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the rule chain name.";  
203 - protected static final String DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device profile name.";  
204 - protected static final String CUSTOMER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the customer title.";  
205 - protected static final String EDGE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the edge name.";  
206 - protected static final String EVENT_TEXT_SEARCH_DESCRIPTION = "The value is not used in searching.";  
207 - protected static final String AUDIT_LOG_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on one of the next properties: entityType, entityName, userName, actionType, actionStatus.";  
208 - protected static final String SORT_PROPERTY_DESCRIPTION = "Property of entity to sort by";  
209 - protected static final String DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title";  
210 - protected static final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city";  
211 - protected static final String RPC_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, expirationTime, request, response";  
212 - protected static final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle";  
213 - protected static final String USER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, firstName, lastName, email";  
214 - protected static final String TENANT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, state, city, address, address2, zip, phone, email";  
215 - protected static final String TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault";  
216 - protected static final String TENANT_PROFILE_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name";  
217 - protected static final String TENANT_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, tenantProfileName, title, email, country, state, city, address, address2, zip, phone, email";  
218 - protected static final String DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, transportType, description, isDefault";  
219 - protected static final String ASSET_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle";  
220 - protected static final String ALARM_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, startTs, endTs, type, ackTs, clearTs, severity, status";  
221 - protected static final String EVENT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, id";  
222 - protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle";  
223 - protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root";  
224 - protected static final String AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, entityType, entityName, userName, actionType, actionStatus";  
225 - protected static final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)";  
226 - protected static final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC";  
227 - protected static final String RPC_STATUS_ALLOWABLE_VALUES = "QUEUED, SENT, DELIVERED, SUCCESSFUL, TIMEOUT, EXPIRED, FAILED";  
228 - protected static final String RULE_CHAIN_TYPES_ALLOWABLE_VALUES = "CORE, EDGE";  
229 - protected static final String TRANSPORT_TYPE_ALLOWABLE_VALUES = "DEFAULT, MQTT, COAP, LWM2M, SNMP";  
230 - protected static final String DEVICE_INFO_DESCRIPTION = "Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. ";  
231 - protected static final String ASSET_INFO_DESCRIPTION = "Asset Info is an extension of the default Asset object that contains information about the assigned customer name. ";  
232 - protected static final String ALARM_INFO_DESCRIPTION = "Alarm Info is an extension of the default Alarm object that also contains name of the alarm originator.";  
233 - protected static final String RELATION_INFO_DESCRIPTION = "Relation Info is an extension of the default Relation object that contains information about the 'from' and 'to' entity names. ";  
234 - protected static final String EDGE_INFO_DESCRIPTION = "Edge Info is an extension of the default Edge object that contains information about the assigned customer name. ";  
235 - protected static final String DEVICE_PROFILE_INFO_DESCRIPTION = "Device Profile Info is a lightweight object that includes main information about Device Profile excluding the heavyweight configuration object. ";  
236 -  
237 - protected static final String DEVICE_NAME_DESCRIPTION = "A string value representing the Device name.";  
238 - protected static final String ASSET_NAME_DESCRIPTION = "A string value representing the Asset name.";  
239 -  
240 - protected static final String EVENT_START_TIME_DESCRIPTION = "Timestamp. Events with creation time before it won't be queried.";  
241 - protected static final String EVENT_END_TIME_DESCRIPTION = "Timestamp. Events with creation time after it won't be queried.";  
242 -  
243 - protected static final String EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Unassignment works in async way - first, 'unassign' notification event pushed to edge queue on platform. ";  
244 - protected static final String EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)" ;  
245 - protected static final String EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Assignment works in async way - first, notification event pushed to edge service queue on platform. ";  
246 - protected static final String EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";  
247 -  
248 - protected static final String MARKDOWN_CODE_BLOCK_START = "```json\n";  
249 - protected static final String MARKDOWN_CODE_BLOCK_END = "\n```";  
250 - protected static final String EVENT_ERROR_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"ERROR\", \"server\": \"ip-172-31-24-152\", " +  
251 - "\"method\": \"onClusterEventMsg\", \"error\": \"Error Message\" }" + MARKDOWN_CODE_BLOCK_END;  
252 - protected static final String EVENT_LC_EVENT_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"LC_EVENT\", \"server\": \"ip-172-31-24-152\", \"event\":" +  
253 - " \"STARTED\", \"status\": \"Success\", \"error\": \"Error Message\" }" + MARKDOWN_CODE_BLOCK_END;  
254 - protected static final String EVENT_STATS_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"STATS\", \"server\": \"ip-172-31-24-152\", \"messagesProcessed\": 10, \"errorsOccurred\": 5 }" + MARKDOWN_CODE_BLOCK_END;  
255 - protected static final String DEBUG_FILTER_OBJ = "\"msgDirectionType\": \"IN\", \"server\": \"ip-172-31-24-152\", \"dataSearch\": \"humidity\", " +  
256 - "\"metadataSearch\": \"deviceName\", \"entityName\": \"DEVICE\", \"relationType\": \"Success\"," +  
257 - " \"entityId\": \"de9d54a0-2b7a-11ec-a3cc-23386423d98f\", \"msgType\": \"POST_TELEMETRY_REQUEST\"," +  
258 - " \"isError\": \"false\", \"error\": \"Error Message\" }";  
259 - protected static final String EVENT_DEBUG_RULE_NODE_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_NODE\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;  
260 - protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_CHAIN\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;  
261 -  
262 - protected static final String RELATION_TYPE_PARAM_DESCRIPTION = "A string value representing relation type between entities. For example, 'Contains', 'Manages'. It can be any string value.";  
263 - protected static final String RELATION_TYPE_GROUP_PARAM_DESCRIPTION = "A string value representing relation type group. For example, 'COMMON'";  
264 -  
265 - protected static final String ADMINISTRATOR_AUTHORITY_ONLY = "Available for users with 'Tenant Administrator' authority only.";  
266 -  
267 - public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";  
268 - protected static final String DEFAULT_DASHBOARD = "defaultDashboardId";  
269 - protected static final String HOME_DASHBOARD = "homeDashboardId";  
270 -  
271 - private static final int DEFAULT_PAGE_SIZE = 1000;  
272 -  
273 private static final ObjectMapper json = new ObjectMapper(); 160 private static final ObjectMapper json = new ObjectMapper();
274 161
275 @Autowired 162 @Autowired
@@ -35,6 +35,8 @@ import java.util.HashSet; @@ -35,6 +35,8 @@ import java.util.HashSet;
35 import java.util.List; 35 import java.util.List;
36 import java.util.Set; 36 import java.util.Set;
37 37
  38 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
  39 +
38 @RestController 40 @RestController
39 @TbCoreComponent 41 @TbCoreComponent
40 @RequestMapping("/api") 42 @RequestMapping("/api")
@@ -47,7 +49,7 @@ public class ComponentDescriptorController extends BaseController { @@ -47,7 +49,7 @@ public class ComponentDescriptorController extends BaseController {
47 49
48 @ApiOperation(value = "Get Component Descriptor (getComponentDescriptorByClazz)", 50 @ApiOperation(value = "Get Component Descriptor (getComponentDescriptorByClazz)",
49 notes = "Gets the Component Descriptor object using class name from the path parameters. " + 51 notes = "Gets the Component Descriptor object using class name from the path parameters. " +
50 - COMPONENT_DESCRIPTOR_DEFINITION) 52 + COMPONENT_DESCRIPTOR_DEFINITION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
51 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") 53 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
52 @RequestMapping(value = "/component/{componentDescriptorClazz:.+}", method = RequestMethod.GET) 54 @RequestMapping(value = "/component/{componentDescriptorClazz:.+}", method = RequestMethod.GET)
53 @ResponseBody 55 @ResponseBody
@@ -64,7 +66,7 @@ public class ComponentDescriptorController extends BaseController { @@ -64,7 +66,7 @@ public class ComponentDescriptorController extends BaseController {
64 66
65 @ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByType)", 67 @ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByType)",
66 notes = "Gets the Component Descriptors using rule node type and optional rule chain type request parameters. " + 68 notes = "Gets the Component Descriptors using rule node type and optional rule chain type request parameters. " +
67 - COMPONENT_DESCRIPTOR_DEFINITION) 69 + COMPONENT_DESCRIPTOR_DEFINITION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
68 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") 70 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
69 @RequestMapping(value = "/components/{componentType}", method = RequestMethod.GET) 71 @RequestMapping(value = "/components/{componentType}", method = RequestMethod.GET)
70 @ResponseBody 72 @ResponseBody
@@ -83,7 +85,7 @@ public class ComponentDescriptorController extends BaseController { @@ -83,7 +85,7 @@ public class ComponentDescriptorController extends BaseController {
83 85
84 @ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByTypes)", 86 @ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByTypes)",
85 notes = "Gets the Component Descriptors using coma separated list of rule node types and optional rule chain type request parameters. " + 87 notes = "Gets the Component Descriptors using coma separated list of rule node types and optional rule chain type request parameters. " +
86 - COMPONENT_DESCRIPTOR_DEFINITION) 88 + COMPONENT_DESCRIPTOR_DEFINITION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
87 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')") 89 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
88 @RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET) 90 @RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET)
89 @ResponseBody 91 @ResponseBody
  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.controller;
  17 +
  18 +public class ControllerConstants {
  19 +
  20 +
  21 + protected static final String NEW_LINE = "\n\n";
  22 + protected static final int DEFAULT_PAGE_SIZE = 1000;
  23 + protected static final String ENTITY_TYPE = "entityType";
  24 + protected static final String CUSTOMER_ID = "customerId";
  25 + protected static final String TENANT_ID = "tenantId";
  26 + protected static final String DEVICE_ID = "deviceId";
  27 + protected static final String RPC_ID = "rpcId";
  28 + protected static final String ENTITY_ID = "entityId";
  29 + protected static final String PAGE_DATA_PARAMETERS = "You can specify parameters to filter the results. " +
  30 + "The result is wrapped with PageData object that allows you to iterate over result set using pagination. " +
  31 + "See the 'Model' tab of the Response Class for more details. ";
  32 + protected static final String DASHBOARD_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  33 + protected static final String RPC_ID_PARAM_DESCRIPTION = "A string value representing the rpc id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  34 + protected static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  35 + protected static final String DEVICE_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  36 + protected static final String TENANT_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the tenant profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  37 + protected static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  38 + protected static final String EDGE_ID_PARAM_DESCRIPTION = "A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  39 + protected static final String CUSTOMER_ID_PARAM_DESCRIPTION = "A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  40 + protected static final String USER_ID_PARAM_DESCRIPTION = "A string value representing the user id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  41 + protected static final String ASSET_ID_PARAM_DESCRIPTION = "A string value representing the asset id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  42 + protected static final String ALARM_ID_PARAM_DESCRIPTION = "A string value representing the alarm id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  43 + protected static final String ENTITY_ID_PARAM_DESCRIPTION = "A string value representing the entity id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  44 + protected static final String OTA_PACKAGE_ID_PARAM_DESCRIPTION = "A string value representing the ota package id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  45 + protected static final String ENTITY_TYPE_PARAM_DESCRIPTION = "A string value representing the entity type. For example, 'DEVICE'";
  46 + protected static final String RULE_CHAIN_ID_PARAM_DESCRIPTION = "A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  47 + protected static final String WIDGET_BUNDLE_ID_PARAM_DESCRIPTION = "A string value representing the widget bundle id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  48 + protected static final String WIDGET_TYPE_ID_PARAM_DESCRIPTION = "A string value representing the widget type id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  49 + protected static final String RESOURCE_ID_PARAM_DESCRIPTION = "A string value representing the resource id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  50 + protected static final String SYSTEM_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' authority.";
  51 + protected static final String SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority.";
  52 + protected static final String TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' authority.";
  53 + protected static final String TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority.";
  54 + protected static final String CUSTOMER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'CUSTOMER_USER' authority.";
  55 + protected static final String AVAILABLE_FOR_ANY_AUTHORIZED_USER = "\n\nAvailable for any authorized user. ";
  56 + protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page";
  57 + protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0";
  58 + protected static final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile";
  59 + protected static final String ASSET_TYPE_DESCRIPTION = "Asset type";
  60 + protected static final String EDGE_TYPE_DESCRIPTION = "A string value representing the edge type. For example, 'default'";
  61 + protected static final String RULE_CHAIN_TYPE_DESCRIPTION = "Rule chain type (CORE or EDGE)";
  62 + protected static final String ASSET_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the asset name.";
  63 + protected static final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title.";
  64 + protected static final String WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the widget bundle title.";
  65 + protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty.";
  66 + protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name.";
  67 + protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email.";
  68 + protected static final String TENANT_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant name.";
  69 + protected static final String TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant profile name.";
  70 + protected static final String RULE_CHAIN_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the rule chain name.";
  71 + protected static final String DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device profile name.";
  72 + protected static final String CUSTOMER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the customer title.";
  73 + protected static final String EDGE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the edge name.";
  74 + protected static final String EVENT_TEXT_SEARCH_DESCRIPTION = "The value is not used in searching.";
  75 + protected static final String AUDIT_LOG_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on one of the next properties: entityType, entityName, userName, actionType, actionStatus.";
  76 + protected static final String SORT_PROPERTY_DESCRIPTION = "Property of entity to sort by";
  77 + protected static final String DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title";
  78 + protected static final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city";
  79 + protected static final String RPC_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, expirationTime, request, response";
  80 + protected static final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle";
  81 + protected static final String USER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, firstName, lastName, email";
  82 + protected static final String TENANT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, state, city, address, address2, zip, phone, email";
  83 + protected static final String TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault";
  84 + protected static final String TENANT_PROFILE_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name";
  85 + protected static final String TENANT_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, tenantProfileName, title, email, country, state, city, address, address2, zip, phone, email";
  86 + protected static final String DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, transportType, description, isDefault";
  87 + protected static final String ASSET_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle";
  88 + protected static final String ALARM_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, startTs, endTs, type, ackTs, clearTs, severity, status";
  89 + protected static final String EVENT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, id";
  90 + protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle";
  91 + protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root";
  92 + protected static final String WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, tenantId";
  93 + protected static final String AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, entityType, entityName, userName, actionType, actionStatus";
  94 + protected static final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)";
  95 + protected static final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC";
  96 + protected static final String RPC_STATUS_ALLOWABLE_VALUES = "QUEUED, SENT, DELIVERED, SUCCESSFUL, TIMEOUT, EXPIRED, FAILED";
  97 + protected static final String RULE_CHAIN_TYPES_ALLOWABLE_VALUES = "CORE, EDGE";
  98 + protected static final String TRANSPORT_TYPE_ALLOWABLE_VALUES = "DEFAULT, MQTT, COAP, LWM2M, SNMP";
  99 + protected static final String DEVICE_INFO_DESCRIPTION = "Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. ";
  100 + protected static final String ASSET_INFO_DESCRIPTION = "Asset Info is an extension of the default Asset object that contains information about the assigned customer name. ";
  101 + protected static final String ALARM_INFO_DESCRIPTION = "Alarm Info is an extension of the default Alarm object that also contains name of the alarm originator.";
  102 + protected static final String RELATION_INFO_DESCRIPTION = "Relation Info is an extension of the default Relation object that contains information about the 'from' and 'to' entity names. ";
  103 + protected static final String EDGE_INFO_DESCRIPTION = "Edge Info is an extension of the default Edge object that contains information about the assigned customer name. ";
  104 + protected static final String DEVICE_PROFILE_INFO_DESCRIPTION = "Device Profile Info is a lightweight object that includes main information about Device Profile excluding the heavyweight configuration object. ";
  105 + protected static final String QUEUE_SERVICE_TYPE_DESCRIPTION = "Service type (implemented only for the TB-RULE-ENGINE)";
  106 + protected static final String QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES = "TB-RULE-ENGINE, TB-CORE, TB-TRANSPORT, JS-EXECUTOR";
  107 + protected static final String OTA_PACKAGE_INFO_DESCRIPTION = "OTA Package Info is a lightweight object that includes main information about the OTA Package excluding the heavyweight data. ";
  108 + protected static final String OTA_PACKAGE_DESCRIPTION = "OTA Package is a heavyweight object that includes main information about the OTA Package and also data. ";
  109 + protected static final String OTA_PACKAGE_CHECKSUM_ALGORITHM_ALLOWABLE_VALUES = "MD5, SHA256, SHA384, SHA512, CRC32, MURMUR3_32, MURMUR3_128";
  110 + protected static final String OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the ota package title.";
  111 + protected static final String OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, type, title, version, tag, url, fileName, dataSize, checksum";
  112 + protected static final String RESOURCE_INFO_DESCRIPTION = "Resource Info is a lightweight object that includes main information about the Resource excluding the heavyweight data. ";
  113 + protected static final String RESOURCE_DESCRIPTION = "Resource is a heavyweight object that includes main information about the Resource and also data. ";
  114 +
  115 + protected static final String RESOURCE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the resource title.";
  116 + protected static final String RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, resourceType, tenantId";
  117 + protected static final String LWM2M_OBJECT_DESCRIPTION = "LwM2M Object is a object that includes information about the LwM2M model which can be used in transport configuration for the LwM2M device profile. ";
  118 + protected static final String LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name";
  119 +
  120 + protected static final String DEVICE_NAME_DESCRIPTION = "A string value representing the Device name.";
  121 + protected static final String ASSET_NAME_DESCRIPTION = "A string value representing the Asset name.";
  122 +
  123 + protected static final String EVENT_START_TIME_DESCRIPTION = "Timestamp. Events with creation time before it won't be queried.";
  124 + protected static final String EVENT_END_TIME_DESCRIPTION = "Timestamp. Events with creation time after it won't be queried.";
  125 +
  126 + protected static final String EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Unassignment works in async way - first, 'unassign' notification event pushed to edge queue on platform. ";
  127 + protected static final String EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";
  128 + protected static final String EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Assignment works in async way - first, notification event pushed to edge service queue on platform. ";
  129 + protected static final String EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";
  130 +
  131 + protected static final String MARKDOWN_CODE_BLOCK_START = "```json\n";
  132 + protected static final String MARKDOWN_CODE_BLOCK_END = "\n```";
  133 + protected static final String EVENT_ERROR_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"ERROR\", \"server\": \"ip-172-31-24-152\", " +
  134 + "\"method\": \"onClusterEventMsg\", \"error\": \"Error Message\" }" + MARKDOWN_CODE_BLOCK_END;
  135 + protected static final String EVENT_LC_EVENT_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"LC_EVENT\", \"server\": \"ip-172-31-24-152\", \"event\":" +
  136 + " \"STARTED\", \"status\": \"Success\", \"error\": \"Error Message\" }" + MARKDOWN_CODE_BLOCK_END;
  137 + protected static final String EVENT_STATS_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"STATS\", \"server\": \"ip-172-31-24-152\", \"messagesProcessed\": 10, \"errorsOccurred\": 5 }" + MARKDOWN_CODE_BLOCK_END;
  138 + protected static final String DEBUG_FILTER_OBJ = "\"msgDirectionType\": \"IN\", \"server\": \"ip-172-31-24-152\", \"dataSearch\": \"humidity\", " +
  139 + "\"metadataSearch\": \"deviceName\", \"entityName\": \"DEVICE\", \"relationType\": \"Success\"," +
  140 + " \"entityId\": \"de9d54a0-2b7a-11ec-a3cc-23386423d98f\", \"msgType\": \"POST_TELEMETRY_REQUEST\"," +
  141 + " \"isError\": \"false\", \"error\": \"Error Message\" }";
  142 + protected static final String EVENT_DEBUG_RULE_NODE_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_NODE\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;
  143 + protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_CHAIN\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;
  144 +
  145 + protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE +
  146 + "Provides a hint about the data type of the entity field that is defined in the filter key. " +
  147 + "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." +
  148 + "The following filter value types and corresponding predicate operations are supported: " + NEW_LINE +
  149 + " * 'STRING' - used to filter any 'String' or 'JSON' values. Operations: EQUAL, NOT_EQUAL, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS; \n" +
  150 + " * 'NUMERIC' - used for 'Long' and 'Double' values. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n" +
  151 + " * 'BOOLEAN' - used for boolean values. Operations: EQUAL, NOT_EQUAL;\n" +
  152 + " * 'DATE_TIME' - similar to numeric, transforms value to milliseconds since epoch. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n";
  153 +
  154 + protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
  155 + "{\n" +
  156 + " \"schedule\":{\n" +
  157 + " \"type\":\"SPECIFIC_TIME\",\n" +
  158 + " \"endsOn\":64800000,\n" +
  159 + " \"startsOn\":43200000,\n" +
  160 + " \"timezone\":\"Europe/Kiev\",\n" +
  161 + " \"daysOfWeek\":[\n" +
  162 + " 1,\n" +
  163 + " 3,\n" +
  164 + " 5\n" +
  165 + " ]\n" +
  166 + " }\n" +
  167 + "}" +
  168 + MARKDOWN_CODE_BLOCK_END;
  169 + protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
  170 + "{\n" +
  171 + " \"schedule\":{\n" +
  172 + " \"type\":\"CUSTOM\",\n" +
  173 + " \"items\":[\n" +
  174 + " {\n" +
  175 + " \"endsOn\":0,\n" +
  176 + " \"enabled\":false,\n" +
  177 + " \"startsOn\":0,\n" +
  178 + " \"dayOfWeek\":1\n" +
  179 + " },\n" +
  180 + " {\n" +
  181 + " \"endsOn\":64800000,\n" +
  182 + " \"enabled\":true,\n" +
  183 + " \"startsOn\":43200000,\n" +
  184 + " \"dayOfWeek\":2\n" +
  185 + " },\n" +
  186 + " {\n" +
  187 + " \"endsOn\":0,\n" +
  188 + " \"enabled\":false,\n" +
  189 + " \"startsOn\":0,\n" +
  190 + " \"dayOfWeek\":3\n" +
  191 + " },\n" +
  192 + " {\n" +
  193 + " \"endsOn\":57600000,\n" +
  194 + " \"enabled\":true,\n" +
  195 + " \"startsOn\":36000000,\n" +
  196 + " \"dayOfWeek\":4\n" +
  197 + " },\n" +
  198 + " {\n" +
  199 + " \"endsOn\":0,\n" +
  200 + " \"enabled\":false,\n" +
  201 + " \"startsOn\":0,\n" +
  202 + " \"dayOfWeek\":5\n" +
  203 + " },\n" +
  204 + " {\n" +
  205 + " \"endsOn\":0,\n" +
  206 + " \"enabled\":false,\n" +
  207 + " \"startsOn\":0,\n" +
  208 + " \"dayOfWeek\":6\n" +
  209 + " },\n" +
  210 + " {\n" +
  211 + " \"endsOn\":0,\n" +
  212 + " \"enabled\":false,\n" +
  213 + " \"startsOn\":0,\n" +
  214 + " \"dayOfWeek\":7\n" +
  215 + " }\n" +
  216 + " ],\n" +
  217 + " \"timezone\":\"Europe/Kiev\"\n" +
  218 + " }\n" +
  219 + "}" +
  220 + MARKDOWN_CODE_BLOCK_END;
  221 + protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "\"schedule\": null" + MARKDOWN_CODE_BLOCK_END;
  222 +
  223 + protected static final String DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
  224 + "{\n" +
  225 + " \"spec\":{\n" +
  226 + " \"type\":\"REPEATING\",\n" +
  227 + " \"predicate\":{\n" +
  228 + " \"userValue\":null,\n" +
  229 + " \"defaultValue\":5,\n" +
  230 + " \"dynamicValue\":{\n" +
  231 + " \"inherit\":true,\n" +
  232 + " \"sourceType\":\"CURRENT_DEVICE\",\n" +
  233 + " \"sourceAttribute\":\"tempAttr\"\n" +
  234 + " }\n" +
  235 + " }\n" +
  236 + " }\n" +
  237 + "}" +
  238 + MARKDOWN_CODE_BLOCK_END;
  239 + protected static final String DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
  240 + "{\n" +
  241 + " \"spec\":{\n" +
  242 + " \"type\":\"DURATION\",\n" +
  243 + " \"unit\":\"MINUTES\",\n" +
  244 + " \"predicate\":{\n" +
  245 + " \"userValue\":null,\n" +
  246 + " \"defaultValue\":30,\n" +
  247 + " \"dynamicValue\":null\n" +
  248 + " }\n" +
  249 + " }\n" +
  250 + "}" +
  251 + MARKDOWN_CODE_BLOCK_END;
  252 +
  253 + protected static final String RELATION_TYPE_PARAM_DESCRIPTION = "A string value representing relation type between entities. For example, 'Contains', 'Manages'. It can be any string value.";
  254 + protected static final String RELATION_TYPE_GROUP_PARAM_DESCRIPTION = "A string value representing relation type group. For example, 'COMMON'";
  255 +
  256 + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
  257 + protected static final String DEFAULT_DASHBOARD = "defaultDashboardId";
  258 + protected static final String HOME_DASHBOARD = "homeDashboardId";
  259 +
  260 + protected static final String SINGLE_ENTITY = "\n\n## Single Entity\n\n" +
  261 + "Allows to filter only one entity based on the id. For example, this entity filter selects certain device:\n\n" +
  262 + MARKDOWN_CODE_BLOCK_START +
  263 + "{\n" +
  264 + " \"type\": \"singleEntity\",\n" +
  265 + " \"singleEntity\": {\n" +
  266 + " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +
  267 + " \"entityType\": \"DEVICE\"\n" +
  268 + " }\n" +
  269 + "}" +
  270 + MARKDOWN_CODE_BLOCK_END +
  271 + "";
  272 +
  273 + protected static final String ENTITY_LIST = "\n\n## Entity List Filter\n\n" +
  274 + "Allows to filter entities of the same type using their ids. For example, this entity filter selects two devices:\n\n" +
  275 + MARKDOWN_CODE_BLOCK_START +
  276 + "{\n" +
  277 + " \"type\": \"entityList\",\n" +
  278 + " \"entityType\": \"DEVICE\",\n" +
  279 + " \"entityList\": [\n" +
  280 + " \"e6501f30-2a7a-11ec-94eb-213c95f54092\",\n" +
  281 + " \"e6657bf0-2a7a-11ec-94eb-213c95f54092\"\n" +
  282 + " ]\n" +
  283 + "}" +
  284 + MARKDOWN_CODE_BLOCK_END +
  285 + "";
  286 +
  287 + protected static final String ENTITY_NAME = "\n\n## Entity Name Filter\n\n" +
  288 + "Allows to filter entities of the same type using the **'starts with'** expression over entity name. " +
  289 + "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n" +
  290 + MARKDOWN_CODE_BLOCK_START +
  291 + "{\n" +
  292 + " \"type\": \"entityName\",\n" +
  293 + " \"entityType\": \"DEVICE\",\n" +
  294 + " \"entityNameFilter\": \"Air Quality\"\n" +
  295 + "}" +
  296 + MARKDOWN_CODE_BLOCK_END +
  297 + "";
  298 +
  299 + protected static final String ENTITY_TYPE_FILTER = "\n\n## Entity Type Filter\n\n" +
  300 + "Allows to filter entities based on their type (CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, etc)" +
  301 + "For example, this entity filter selects all tenant customers:\n\n" +
  302 + MARKDOWN_CODE_BLOCK_START +
  303 + "{\n" +
  304 + " \"type\": \"entityType\",\n" +
  305 + " \"entityType\": \"CUSTOMER\"\n" +
  306 + "}" +
  307 + MARKDOWN_CODE_BLOCK_END +
  308 + "";
  309 +
  310 + protected static final String ASSET_TYPE = "\n\n## Asset Type Filter\n\n" +
  311 + "Allows to filter assets based on their type and the **'starts with'** expression over their name. " +
  312 + "For example, this entity filter selects all 'charging station' assets which name starts with 'Tesla':\n\n" +
  313 + MARKDOWN_CODE_BLOCK_START +
  314 + "{\n" +
  315 + " \"type\": \"assetType\",\n" +
  316 + " \"assetType\": \"charging station\",\n" +
  317 + " \"assetNameFilter\": \"Tesla\"\n" +
  318 + "}" +
  319 + MARKDOWN_CODE_BLOCK_END +
  320 + "";
  321 +
  322 + protected static final String DEVICE_TYPE = "\n\n## Device Type Filter\n\n" +
  323 + "Allows to filter devices based on their type and the **'starts with'** expression over their name. " +
  324 + "For example, this entity filter selects all 'Temperature Sensor' devices which name starts with 'ABC':\n\n" +
  325 + MARKDOWN_CODE_BLOCK_START +
  326 + "{\n" +
  327 + " \"type\": \"deviceType\",\n" +
  328 + " \"deviceType\": \"Temperature Sensor\",\n" +
  329 + " \"deviceNameFilter\": \"ABC\"\n" +
  330 + "}" +
  331 + MARKDOWN_CODE_BLOCK_END +
  332 + "";
  333 +
  334 + protected static final String EDGE_TYPE = "\n\n## Edge Type Filter\n\n" +
  335 + "Allows to filter edge instances based on their type and the **'starts with'** expression over their name. " +
  336 + "For example, this entity filter selects all 'Factory' edge instances which name starts with 'Nevada':\n\n" +
  337 + MARKDOWN_CODE_BLOCK_START +
  338 + "{\n" +
  339 + " \"type\": \"edgeType\",\n" +
  340 + " \"edgeType\": \"Factory\",\n" +
  341 + " \"edgeNameFilter\": \"Nevada\"\n" +
  342 + "}" +
  343 + MARKDOWN_CODE_BLOCK_END +
  344 + "";
  345 +
  346 + protected static final String ENTITY_VIEW_TYPE = "\n\n## Entity View Filter\n\n" +
  347 + "Allows to filter entity views based on their type and the **'starts with'** expression over their name. " +
  348 + "For example, this entity filter selects all 'Concrete Mixer' entity views which name starts with 'CAT':\n\n" +
  349 + MARKDOWN_CODE_BLOCK_START +
  350 + "{\n" +
  351 + " \"type\": \"entityViewType\",\n" +
  352 + " \"entityViewType\": \"Concrete Mixer\",\n" +
  353 + " \"entityViewNameFilter\": \"CAT\"\n" +
  354 + "}" +
  355 + MARKDOWN_CODE_BLOCK_END +
  356 + "";
  357 +
  358 + protected static final String API_USAGE = "\n\n## Api Usage Filter\n\n" +
  359 + "Allows to query for Api Usage based on optional customer id. If the customer id is not set, returns current tenant API usage." +
  360 + "For example, this entity filter selects the 'Api Usage' entity for customer with id 'e6501f30-2a7a-11ec-94eb-213c95f54092':\n\n" +
  361 + MARKDOWN_CODE_BLOCK_START +
  362 + "{\n" +
  363 + " \"type\": \"apiUsageState\",\n" +
  364 + " \"customerId\": {\n" +
  365 + " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +
  366 + " \"entityType\": \"CUSTOMER\"\n" +
  367 + " }\n" +
  368 + "}" +
  369 + MARKDOWN_CODE_BLOCK_END +
  370 + "";
  371 +
  372 + protected static final String MAX_LEVEL_DESCRIPTION = "Possible direction values are 'TO' and 'FROM'. The 'maxLevel' defines how many relation levels should the query search 'recursively'. ";
  373 + protected static final String FETCH_LAST_LEVEL_ONLY_DESCRIPTION = "Assuming the 'maxLevel' is > 1, the 'fetchLastLevelOnly' defines either to return all related entities or only entities that are on the last level of relations. ";
  374 +
  375 + protected static final String RELATIONS_QUERY_FILTER = "\n\n## Relations Query Filter\n\n" +
  376 + "Allows to filter entities that are related to the provided root entity. " +
  377 + MAX_LEVEL_DESCRIPTION +
  378 + FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
  379 + "The 'filter' object allows you to define the relation type and set of acceptable entity types to search for. " +
  380 + "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only those who match the 'filters'.\n\n" +
  381 + "For example, this entity filter selects all devices and assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092':\n\n" +
  382 + MARKDOWN_CODE_BLOCK_START +
  383 + "{\n" +
  384 + " \"type\": \"relationsQuery\",\n" +
  385 + " \"rootEntity\": {\n" +
  386 + " \"entityType\": \"ASSET\",\n" +
  387 + " \"id\": \"e51de0c0-2a7a-11ec-94eb-213c95f54092\"\n" +
  388 + " },\n" +
  389 + " \"direction\": \"FROM\",\n" +
  390 + " \"maxLevel\": 1,\n" +
  391 + " \"fetchLastLevelOnly\": false,\n" +
  392 + " \"filters\": [\n" +
  393 + " {\n" +
  394 + " \"relationType\": \"Contains\",\n" +
  395 + " \"entityTypes\": [\n" +
  396 + " \"DEVICE\",\n" +
  397 + " \"ASSET\"\n" +
  398 + " ]\n" +
  399 + " }\n" +
  400 + " ]\n" +
  401 + "}" +
  402 + MARKDOWN_CODE_BLOCK_END +
  403 + "";
  404 +
  405 +
  406 + protected static final String ASSET_QUERY_FILTER = "\n\n## Asset Search Query\n\n" +
  407 + "Allows to filter assets that are related to the provided root entity. Filters related assets based on the relation type and set of asset types. " +
  408 + MAX_LEVEL_DESCRIPTION +
  409 + FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
  410 + "The 'relationType' defines the type of the relation to search for. " +
  411 + "The 'assetTypes' defines the type of the asset to search for. " +
  412 + "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only assets that match 'relationType' and 'assetTypes' conditions.\n\n" +
  413 + "For example, this entity filter selects 'charging station' assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
  414 + MARKDOWN_CODE_BLOCK_START +
  415 + "{\n" +
  416 + " \"type\": \"assetSearchQuery\",\n" +
  417 + " \"rootEntity\": {\n" +
  418 + " \"entityType\": \"ASSET\",\n" +
  419 + " \"id\": \"e51de0c0-2a7a-11ec-94eb-213c95f54092\"\n" +
  420 + " },\n" +
  421 + " \"direction\": \"FROM\",\n" +
  422 + " \"maxLevel\": 1,\n" +
  423 + " \"fetchLastLevelOnly\": false,\n" +
  424 + " \"relationType\": \"Contains\",\n" +
  425 + " \"assetTypes\": [\n" +
  426 + " \"charging station\"\n" +
  427 + " ]\n" +
  428 + "}" +
  429 + MARKDOWN_CODE_BLOCK_END +
  430 + "";
  431 +
  432 + protected static final String DEVICE_QUERY_FILTER = "\n\n## Device Search Query\n\n" +
  433 + "Allows to filter devices that are related to the provided root entity. Filters related devices based on the relation type and set of device types. " +
  434 + MAX_LEVEL_DESCRIPTION +
  435 + FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
  436 + "The 'relationType' defines the type of the relation to search for. " +
  437 + "The 'deviceTypes' defines the type of the device to search for. " +
  438 + "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +
  439 + "For example, this entity filter selects 'Charging port' and 'Air Quality Sensor' devices which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
  440 + MARKDOWN_CODE_BLOCK_START +
  441 + "{\n" +
  442 + " \"type\": \"deviceSearchQuery\",\n" +
  443 + " \"rootEntity\": {\n" +
  444 + " \"entityType\": \"ASSET\",\n" +
  445 + " \"id\": \"e52b0020-2a7a-11ec-94eb-213c95f54092\"\n" +
  446 + " },\n" +
  447 + " \"direction\": \"FROM\",\n" +
  448 + " \"maxLevel\": 2,\n" +
  449 + " \"fetchLastLevelOnly\": true,\n" +
  450 + " \"relationType\": \"Contains\",\n" +
  451 + " \"deviceTypes\": [\n" +
  452 + " \"Air Quality Sensor\",\n" +
  453 + " \"Charging port\"\n" +
  454 + " ]\n" +
  455 + "}" +
  456 + MARKDOWN_CODE_BLOCK_END +
  457 + "";
  458 +
  459 + protected static final String EV_QUERY_FILTER = "\n\n## Entity View Query\n\n" +
  460 + "Allows to filter entity views that are related to the provided root entity. Filters related entity views based on the relation type and set of entity view types. " +
  461 + MAX_LEVEL_DESCRIPTION +
  462 + FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
  463 + "The 'relationType' defines the type of the relation to search for. " +
  464 + "The 'entityViewTypes' defines the type of the entity view to search for. " +
  465 + "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +
  466 + "For example, this entity filter selects 'Concrete mixer' entity views which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
  467 + MARKDOWN_CODE_BLOCK_START +
  468 + "{\n" +
  469 + " \"type\": \"entityViewSearchQuery\",\n" +
  470 + " \"rootEntity\": {\n" +
  471 + " \"entityType\": \"ASSET\",\n" +
  472 + " \"id\": \"e52b0020-2a7a-11ec-94eb-213c95f54092\"\n" +
  473 + " },\n" +
  474 + " \"direction\": \"FROM\",\n" +
  475 + " \"maxLevel\": 1,\n" +
  476 + " \"fetchLastLevelOnly\": false,\n" +
  477 + " \"relationType\": \"Contains\",\n" +
  478 + " \"entityViewTypes\": [\n" +
  479 + " \"Concrete mixer\"\n" +
  480 + " ]\n" +
  481 + "}" +
  482 + MARKDOWN_CODE_BLOCK_END +
  483 + "";
  484 +
  485 + protected static final String EDGE_QUERY_FILTER = "\n\n## Edge Search Query\n\n" +
  486 + "Allows to filter edge instances that are related to the provided root entity. Filters related edge instances based on the relation type and set of edge types. " +
  487 + MAX_LEVEL_DESCRIPTION +
  488 + FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
  489 + "The 'relationType' defines the type of the relation to search for. " +
  490 + "The 'deviceTypes' defines the type of the device to search for. " +
  491 + "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +
  492 + "For example, this entity filter selects 'Factory' edge instances which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
  493 + MARKDOWN_CODE_BLOCK_START +
  494 + "{\n" +
  495 + " \"type\": \"deviceSearchQuery\",\n" +
  496 + " \"rootEntity\": {\n" +
  497 + " \"entityType\": \"ASSET\",\n" +
  498 + " \"id\": \"e52b0020-2a7a-11ec-94eb-213c95f54092\"\n" +
  499 + " },\n" +
  500 + " \"direction\": \"FROM\",\n" +
  501 + " \"maxLevel\": 2,\n" +
  502 + " \"fetchLastLevelOnly\": true,\n" +
  503 + " \"relationType\": \"Contains\",\n" +
  504 + " \"edgeTypes\": [\n" +
  505 + " \"Factory\"\n" +
  506 + " ]\n" +
  507 + "}" +
  508 + MARKDOWN_CODE_BLOCK_END +
  509 + "";
  510 +
  511 + protected static final String EMPTY = "\n\n## Entity Type Filter\n\n" +
  512 + "Allows to filter multiple entities of the same type using the **'starts with'** expression over entity name. " +
  513 + "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n" +
  514 + MARKDOWN_CODE_BLOCK_START +
  515 + "" +
  516 + MARKDOWN_CODE_BLOCK_END +
  517 + "";
  518 +
  519 + protected static final String ENTITY_FILTERS =
  520 + "\n\n # Entity Filters" +
  521 + "\nEntity Filter body depends on the 'type' parameter. Let's review available entity filter types. In fact, they do correspond to available dashboard aliases." +
  522 + SINGLE_ENTITY + ENTITY_LIST + ENTITY_NAME + ENTITY_TYPE_FILTER + ASSET_TYPE + DEVICE_TYPE + EDGE_TYPE + ENTITY_VIEW_TYPE + API_USAGE + RELATIONS_QUERY_FILTER
  523 + + ASSET_QUERY_FILTER + DEVICE_QUERY_FILTER + EV_QUERY_FILTER + EDGE_QUERY_FILTER;
  524 +
  525 + protected static final String FILTER_KEY = "\n\n## Filter Key\n\n" +
  526 + "Filter Key defines either entity field, attribute or telemetry. It is a JSON object that consists the key name and type. " +
  527 + "The following filter key types are supported: \n\n" +
  528 + " * 'CLIENT_ATTRIBUTE' - used for client attributes; \n" +
  529 + " * 'SHARED_ATTRIBUTE' - used for shared attributes; \n" +
  530 + " * 'SERVER_ATTRIBUTE' - used for server attributes; \n" +
  531 + " * 'ATTRIBUTE' - used for any of the above; \n" +
  532 + " * 'TIME_SERIES' - used for time-series values; \n" +
  533 + " * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type; \n" +
  534 + " * 'ALARM_FIELD' - similar to entity field, but is used in alarm queries only; \n" +
  535 + "\n\n Let's review the example:\n\n" +
  536 + MARKDOWN_CODE_BLOCK_START +
  537 + "{\n" +
  538 + " \"type\": \"TIME_SERIES\",\n" +
  539 + " \"key\": \"temperature\"\n" +
  540 + "}" +
  541 + MARKDOWN_CODE_BLOCK_END +
  542 + "";
  543 +
  544 + protected static final String FILTER_PREDICATE = "\n\n## Filter Predicate\n\n" +
  545 + "Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +
  546 + "Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." +
  547 + "\n\nSimple predicate example to check 'value < 100': \n\n" +
  548 + MARKDOWN_CODE_BLOCK_START +
  549 + "{\n" +
  550 + " \"operation\": \"LESS\",\n" +
  551 + " \"value\": {\n" +
  552 + " \"defaultValue\": 100,\n" +
  553 + " \"dynamicValue\": null\n" +
  554 + " },\n" +
  555 + " \"type\": \"NUMERIC\"\n" +
  556 + "}" +
  557 + MARKDOWN_CODE_BLOCK_END +
  558 + "\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n" +
  559 + MARKDOWN_CODE_BLOCK_START +
  560 + "{\n" +
  561 + " \"type\": \"COMPLEX\",\n" +
  562 + " \"operation\": \"OR\",\n" +
  563 + " \"predicates\": [\n" +
  564 + " {\n" +
  565 + " \"operation\": \"LESS\",\n" +
  566 + " \"value\": {\n" +
  567 + " \"defaultValue\": 10,\n" +
  568 + " \"dynamicValue\": null\n" +
  569 + " },\n" +
  570 + " \"type\": \"NUMERIC\"\n" +
  571 + " },\n" +
  572 + " {\n" +
  573 + " \"operation\": \"GREATER\",\n" +
  574 + " \"value\": {\n" +
  575 + " \"defaultValue\": 20,\n" +
  576 + " \"dynamicValue\": null\n" +
  577 + " },\n" +
  578 + " \"type\": \"NUMERIC\"\n" +
  579 + " }\n" +
  580 + " ]\n" +
  581 + "}" +
  582 + MARKDOWN_CODE_BLOCK_END +
  583 + "\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n" +
  584 + MARKDOWN_CODE_BLOCK_START +
  585 + "{\n" +
  586 + " \"type\": \"COMPLEX\",\n" +
  587 + " \"operation\": \"OR\",\n" +
  588 + " \"predicates\": [\n" +
  589 + " {\n" +
  590 + " \"operation\": \"LESS\",\n" +
  591 + " \"value\": {\n" +
  592 + " \"defaultValue\": 10,\n" +
  593 + " \"dynamicValue\": null\n" +
  594 + " },\n" +
  595 + " \"type\": \"NUMERIC\"\n" +
  596 + " },\n" +
  597 + " {\n" +
  598 + " \"type\": \"COMPLEX\",\n" +
  599 + " \"operation\": \"AND\",\n" +
  600 + " \"predicates\": [\n" +
  601 + " {\n" +
  602 + " \"operation\": \"GREATER\",\n" +
  603 + " \"value\": {\n" +
  604 + " \"defaultValue\": 50,\n" +
  605 + " \"dynamicValue\": null\n" +
  606 + " },\n" +
  607 + " \"type\": \"NUMERIC\"\n" +
  608 + " },\n" +
  609 + " {\n" +
  610 + " \"operation\": \"LESS\",\n" +
  611 + " \"value\": {\n" +
  612 + " \"defaultValue\": 60,\n" +
  613 + " \"dynamicValue\": null\n" +
  614 + " },\n" +
  615 + " \"type\": \"NUMERIC\"\n" +
  616 + " }\n" +
  617 + " ]\n" +
  618 + " }\n" +
  619 + " ]\n" +
  620 + "}" +
  621 + MARKDOWN_CODE_BLOCK_END +
  622 + "\n\n You may also want to replace hardcoded values (for example, temperature > 20) with the more dynamic " +
  623 + "expression (for example, temperature > 'value of the tenant attribute with key 'temperatureThreshold'). " +
  624 + "It is possible to use 'dynamicValue' to define attribute of the tenant, customer or user that is performing the API call. " +
  625 + "See example below: \n\n" +
  626 + MARKDOWN_CODE_BLOCK_START +
  627 + "{\n" +
  628 + " \"operation\": \"GREATER\",\n" +
  629 + " \"value\": {\n" +
  630 + " \"defaultValue\": 0,\n" +
  631 + " \"dynamicValue\": {\n" +
  632 + " \"sourceType\": \"CURRENT_USER\",\n" +
  633 + " \"sourceAttribute\": \"temperatureThreshold\"\n" +
  634 + " }\n" +
  635 + " },\n" +
  636 + " \"type\": \"NUMERIC\"\n" +
  637 + "}" +
  638 + MARKDOWN_CODE_BLOCK_END +
  639 + "\n\n Note that you may use 'CURRENT_USER', 'CURRENT_CUSTOMER' and 'CURRENT_TENANT' as a 'sourceType'. The 'defaultValue' is used when the attribute with such a name is not defined for the chosen source.";
  640 +
  641 + protected static final String KEY_FILTERS =
  642 + "\n\n # Key Filters" +
  643 + "\nKey Filter allows you to define complex logical expressions over entity field, attribute or latest time-series value. The filter is defined using 'key', 'valueType' and 'predicate' objects. " +
  644 + "Single Entity Query may have zero, one or multiple predicates. If multiple filters are defined, they are evaluated using logical 'AND'. " +
  645 + "The example below checks that temperature of the entity is above 20 degrees:" +
  646 + "\n\n" + MARKDOWN_CODE_BLOCK_START +
  647 + "{\n" +
  648 + " \"key\": {\n" +
  649 + " \"type\": \"TIME_SERIES\",\n" +
  650 + " \"key\": \"temperature\"\n" +
  651 + " },\n" +
  652 + " \"valueType\": \"NUMERIC\",\n" +
  653 + " \"predicate\": {\n" +
  654 + " \"operation\": \"GREATER\",\n" +
  655 + " \"value\": {\n" +
  656 + " \"defaultValue\": 20,\n" +
  657 + " \"dynamicValue\": null\n" +
  658 + " },\n" +
  659 + " \"type\": \"NUMERIC\"\n" +
  660 + " }\n" +
  661 + "}" +
  662 + MARKDOWN_CODE_BLOCK_END +
  663 + "\n\n Now let's review 'key', 'valueType' and 'predicate' objects in detail."
  664 + + FILTER_KEY + FILTER_VALUE_TYPE + FILTER_PREDICATE;
  665 +
  666 + protected static final String ENTITY_COUNT_QUERY_DESCRIPTION =
  667 + "Allows to run complex queries to search the count of platform entities (devices, assets, customers, etc) " +
  668 + "based on the combination of main entity filter and multiple key filters. Returns the number of entities that match the query definition.\n\n" +
  669 + "# Query Definition\n\n" +
  670 + "\n\nMain **entity filter** is mandatory and defines generic search criteria. " +
  671 + "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +
  672 + "\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " +
  673 + "main entity fields (name, label, type, etc), attributes and telemetry. " +
  674 + "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." +
  675 + "\n\nLet's review the example:" +
  676 + "\n\n" + MARKDOWN_CODE_BLOCK_START +
  677 + "{\n" +
  678 + " \"entityFilter\": {\n" +
  679 + " \"type\": \"entityType\",\n" +
  680 + " \"entityType\": \"DEVICE\"\n" +
  681 + " },\n" +
  682 + " \"keyFilters\": [\n" +
  683 + " {\n" +
  684 + " \"key\": {\n" +
  685 + " \"type\": \"ATTRIBUTE\",\n" +
  686 + " \"key\": \"active\"\n" +
  687 + " },\n" +
  688 + " \"valueType\": \"BOOLEAN\",\n" +
  689 + " \"predicate\": {\n" +
  690 + " \"operation\": \"EQUAL\",\n" +
  691 + " \"value\": {\n" +
  692 + " \"defaultValue\": true,\n" +
  693 + " \"dynamicValue\": null\n" +
  694 + " },\n" +
  695 + " \"type\": \"BOOLEAN\"\n" +
  696 + " }\n" +
  697 + " }\n" +
  698 + " ]\n" +
  699 + "}" +
  700 + MARKDOWN_CODE_BLOCK_END +
  701 + "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +
  702 + ENTITY_FILTERS +
  703 + KEY_FILTERS +
  704 + ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  705 +
  706 + protected static final String ENTITY_DATA_QUERY_DESCRIPTION =
  707 + "Allows to run complex queries over platform entities (devices, assets, customers, etc) " +
  708 + "based on the combination of main entity filter and multiple key filters. " +
  709 + "Returns the paginated result of the query that contains requested entity fields and latest values of requested attributes and time-series data.\n\n" +
  710 + "# Query Definition\n\n" +
  711 + "\n\nMain **entity filter** is mandatory and defines generic search criteria. " +
  712 + "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +
  713 + "\n\nOptional **key filters** allow to filter results of the **entity filter** by complex criteria against " +
  714 + "main entity fields (name, label, type, etc), attributes and telemetry. " +
  715 + "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." +
  716 + "\n\nThe **entity fields** and **latest values** contains list of entity fields and latest attribute/telemetry fields to fetch for each entity." +
  717 + "\n\nThe **page link** contains information about the page to fetch and the sort ordering." +
  718 + "\n\nLet's review the example:" +
  719 + "\n\n" + MARKDOWN_CODE_BLOCK_START +
  720 + "{\n" +
  721 + " \"entityFilter\": {\n" +
  722 + " \"type\": \"entityType\",\n" +
  723 + " \"resolveMultiple\": true,\n" +
  724 + " \"entityType\": \"DEVICE\"\n" +
  725 + " },\n" +
  726 + " \"keyFilters\": [\n" +
  727 + " {\n" +
  728 + " \"key\": {\n" +
  729 + " \"type\": \"TIME_SERIES\",\n" +
  730 + " \"key\": \"temperature\"\n" +
  731 + " },\n" +
  732 + " \"valueType\": \"NUMERIC\",\n" +
  733 + " \"predicate\": {\n" +
  734 + " \"operation\": \"GREATER\",\n" +
  735 + " \"value\": {\n" +
  736 + " \"defaultValue\": 0,\n" +
  737 + " \"dynamicValue\": {\n" +
  738 + " \"sourceType\": \"CURRENT_USER\",\n" +
  739 + " \"sourceAttribute\": \"temperatureThreshold\",\n" +
  740 + " \"inherit\": false\n" +
  741 + " }\n" +
  742 + " },\n" +
  743 + " \"type\": \"NUMERIC\"\n" +
  744 + " }\n" +
  745 + " }\n" +
  746 + " ],\n" +
  747 + " \"entityFields\": [\n" +
  748 + " {\n" +
  749 + " \"type\": \"ENTITY_FIELD\",\n" +
  750 + " \"key\": \"name\"\n" +
  751 + " },\n" +
  752 + " {\n" +
  753 + " \"type\": \"ENTITY_FIELD\",\n" +
  754 + " \"key\": \"label\"\n" +
  755 + " },\n" +
  756 + " {\n" +
  757 + " \"type\": \"ENTITY_FIELD\",\n" +
  758 + " \"key\": \"additionalInfo\"\n" +
  759 + " }\n" +
  760 + " ],\n" +
  761 + " \"latestValues\": [\n" +
  762 + " {\n" +
  763 + " \"type\": \"ATTRIBUTE\",\n" +
  764 + " \"key\": \"model\"\n" +
  765 + " },\n" +
  766 + " {\n" +
  767 + " \"type\": \"TIME_SERIES\",\n" +
  768 + " \"key\": \"temperature\"\n" +
  769 + " }\n" +
  770 + " ],\n" +
  771 + " \"pageLink\": {\n" +
  772 + " \"page\": 0,\n" +
  773 + " \"pageSize\": 10,\n" +
  774 + " \"sortOrder\": {\n" +
  775 + " \"key\": {\n" +
  776 + " \"key\": \"name\",\n" +
  777 + " \"type\": \"ENTITY_FIELD\"\n" +
  778 + " },\n" +
  779 + " \"direction\": \"ASC\"\n" +
  780 + " }\n" +
  781 + " }\n" +
  782 + "}" +
  783 + MARKDOWN_CODE_BLOCK_END +
  784 + "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +
  785 + ENTITY_FILTERS +
  786 + KEY_FILTERS +
  787 + ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  788 +
  789 +
  790 + protected static final String ALARM_DATA_QUERY_DESCRIPTION = "This method description defines how Alarm Data Query extends the Entity Data Query. " +
  791 + "See method 'Find Entity Data by Query' first to get the info about 'Entity Data Query'." +
  792 + "\n\n The platform will first search the entities that match the entity and key filters. Then, the platform will use 'Alarm Page Link' to filter the alarms related to those entities. " +
  793 + "Finally, platform fetch the properties of alarm that are defined in the **'alarmFields'** and combine them with the other entity, attribute and latest time-series fields to return the result. " +
  794 + "\n\n See example of the alarm query below. The query will search first 100 active alarms with type 'Temperature Alarm' or 'Fire Alarm' for any device with current temperature > 0. " +
  795 + "The query will return combination of the entity fields: name of the device, device model and latest temperature reading and alarms fields: createdTime, type, severity and status: " +
  796 + "\n\n" + MARKDOWN_CODE_BLOCK_START +
  797 + "{\n" +
  798 + " \"entityFilter\": {\n" +
  799 + " \"type\": \"entityType\",\n" +
  800 + " \"resolveMultiple\": true,\n" +
  801 + " \"entityType\": \"DEVICE\"\n" +
  802 + " },\n" +
  803 + " \"pageLink\": {\n" +
  804 + " \"page\": 0,\n" +
  805 + " \"pageSize\": 100,\n" +
  806 + " \"textSearch\": null,\n" +
  807 + " \"searchPropagatedAlarms\": false,\n" +
  808 + " \"statusList\": [\n" +
  809 + " \"ACTIVE\"\n" +
  810 + " ],\n" +
  811 + " \"severityList\": [\n" +
  812 + " \"CRITICAL\",\n" +
  813 + " \"MAJOR\"\n" +
  814 + " ],\n" +
  815 + " \"typeList\": [\n" +
  816 + " \"Temperature Alarm\",\n" +
  817 + " \"Fire Alarm\"\n" +
  818 + " ],\n" +
  819 + " \"sortOrder\": {\n" +
  820 + " \"key\": {\n" +
  821 + " \"key\": \"createdTime\",\n" +
  822 + " \"type\": \"ALARM_FIELD\"\n" +
  823 + " },\n" +
  824 + " \"direction\": \"DESC\"\n" +
  825 + " },\n" +
  826 + " \"timeWindow\": 86400000\n" +
  827 + " },\n" +
  828 + " \"keyFilters\": [\n" +
  829 + " {\n" +
  830 + " \"key\": {\n" +
  831 + " \"type\": \"TIME_SERIES\",\n" +
  832 + " \"key\": \"temperature\"\n" +
  833 + " },\n" +
  834 + " \"valueType\": \"NUMERIC\",\n" +
  835 + " \"predicate\": {\n" +
  836 + " \"operation\": \"GREATER\",\n" +
  837 + " \"value\": {\n" +
  838 + " \"defaultValue\": 0,\n" +
  839 + " \"dynamicValue\": null\n" +
  840 + " },\n" +
  841 + " \"type\": \"NUMERIC\"\n" +
  842 + " }\n" +
  843 + " }\n" +
  844 + " ],\n" +
  845 + " \"alarmFields\": [\n" +
  846 + " {\n" +
  847 + " \"type\": \"ALARM_FIELD\",\n" +
  848 + " \"key\": \"createdTime\"\n" +
  849 + " },\n" +
  850 + " {\n" +
  851 + " \"type\": \"ALARM_FIELD\",\n" +
  852 + " \"key\": \"type\"\n" +
  853 + " },\n" +
  854 + " {\n" +
  855 + " \"type\": \"ALARM_FIELD\",\n" +
  856 + " \"key\": \"severity\"\n" +
  857 + " },\n" +
  858 + " {\n" +
  859 + " \"type\": \"ALARM_FIELD\",\n" +
  860 + " \"key\": \"status\"\n" +
  861 + " }\n" +
  862 + " ],\n" +
  863 + " \"entityFields\": [\n" +
  864 + " {\n" +
  865 + " \"type\": \"ENTITY_FIELD\",\n" +
  866 + " \"key\": \"name\"\n" +
  867 + " }\n" +
  868 + " ],\n" +
  869 + " \"latestValues\": [\n" +
  870 + " {\n" +
  871 + " \"type\": \"ATTRIBUTE\",\n" +
  872 + " \"key\": \"model\"\n" +
  873 + " },\n" +
  874 + " {\n" +
  875 + " \"type\": \"TIME_SERIES\",\n" +
  876 + " \"key\": \"temperature\"\n" +
  877 + " }\n" +
  878 + " ]\n" +
  879 + "}" +
  880 + MARKDOWN_CODE_BLOCK_END +
  881 + "";
  882 +
  883 + protected static final String COAP_TRANSPORT_CONFIGURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
  884 + "{\n" +
  885 + " \"type\":\"COAP\",\n" +
  886 + " \"clientSettings\":{\n" +
  887 + " \"edrxCycle\":null,\n" +
  888 + " \"powerMode\":\"DRX\",\n" +
  889 + " \"psmActivityTimer\":null,\n" +
  890 + " \"pagingTransmissionWindow\":null\n" +
  891 + " },\n" +
  892 + " \"coapDeviceTypeConfiguration\":{\n" +
  893 + " \"coapDeviceType\":\"DEFAULT\",\n" +
  894 + " \"transportPayloadTypeConfiguration\":{\n" +
  895 + " \"transportPayloadType\":\"JSON\"\n" +
  896 + " }\n" +
  897 + " }\n" +
  898 + "}"
  899 + + MARKDOWN_CODE_BLOCK_END;
  900 +
  901 + protected static final String TRANSPORT_CONFIGURATION = "# Transport Configuration" + NEW_LINE +
  902 + "5 transport configuration types are available:\n" +
  903 + " * 'DEFAULT';\n" +
  904 + " * 'MQTT';\n" +
  905 + " * 'LWM2M';\n" +
  906 + " * 'COAP';\n" +
  907 + " * 'SNMP'." + NEW_LINE + "Default type supports basic MQTT, HTTP, CoAP and LwM2M transports. " +
  908 + "Please refer to the [docs](https://thingsboard.io/docs/user-guide/device-profiles/#transport-configuration) for more details about other types.\n" +
  909 + "\nSee another example of COAP transport configuration below:" + NEW_LINE + COAP_TRANSPORT_CONFIGURATION_EXAMPLE;
  910 +
  911 + protected static final String ALARM_FILTER_KEY = "## Alarm Filter Key" + NEW_LINE +
  912 + "Filter Key defines either entity field, attribute, telemetry or constant. It is a JSON object that consists the key name and type. The following filter key types are supported:\n" +
  913 + " * 'ATTRIBUTE' - used for attributes values;\n" +
  914 + " * 'TIME_SERIES' - used for time-series values;\n" +
  915 + " * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type;\n" +
  916 + " * 'CONSTANT' - constant value specified." + NEW_LINE + "Let's review the example:" + NEW_LINE +
  917 + MARKDOWN_CODE_BLOCK_START +
  918 + "{\n" +
  919 + " \"type\": \"TIME_SERIES\",\n" +
  920 + " \"key\": \"temperature\"\n" +
  921 + "}" +
  922 + MARKDOWN_CODE_BLOCK_END;
  923 +
  924 + protected static final String DEVICE_PROFILE_FILTER_PREDICATE = NEW_LINE + "## Filter Predicate" + NEW_LINE +
  925 + "Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +
  926 + "Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." + NEW_LINE +
  927 + "Simple predicate example to check 'value < 100': " + NEW_LINE +
  928 + MARKDOWN_CODE_BLOCK_START +
  929 + "{\n" +
  930 + " \"operation\": \"LESS\",\n" +
  931 + " \"value\": {\n" +
  932 + " \"userValue\": null,\n" +
  933 + " \"defaultValue\": 100,\n" +
  934 + " \"dynamicValue\": null\n" +
  935 + " },\n" +
  936 + " \"type\": \"NUMERIC\"\n" +
  937 + "}" +
  938 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  939 + "Complex predicate example, to check 'value < 10 or value > 20': " + NEW_LINE +
  940 + MARKDOWN_CODE_BLOCK_START +
  941 + "{\n" +
  942 + " \"type\": \"COMPLEX\",\n" +
  943 + " \"operation\": \"OR\",\n" +
  944 + " \"predicates\": [\n" +
  945 + " {\n" +
  946 + " \"operation\": \"LESS\",\n" +
  947 + " \"value\": {\n" +
  948 + " \"userValue\": null,\n" +
  949 + " \"defaultValue\": 10,\n" +
  950 + " \"dynamicValue\": null\n" +
  951 + " },\n" +
  952 + " \"type\": \"NUMERIC\"\n" +
  953 + " },\n" +
  954 + " {\n" +
  955 + " \"operation\": \"GREATER\",\n" +
  956 + " \"value\": {\n" +
  957 + " \"userValue\": null,\n" +
  958 + " \"defaultValue\": 20,\n" +
  959 + " \"dynamicValue\": null\n" +
  960 + " },\n" +
  961 + " \"type\": \"NUMERIC\"\n" +
  962 + " }\n" +
  963 + " ]\n" +
  964 + "}" +
  965 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  966 + "More complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': " + NEW_LINE +
  967 + MARKDOWN_CODE_BLOCK_START +
  968 + "{\n" +
  969 + " \"type\": \"COMPLEX\",\n" +
  970 + " \"operation\": \"OR\",\n" +
  971 + " \"predicates\": [\n" +
  972 + " {\n" +
  973 + " \"operation\": \"LESS\",\n" +
  974 + " \"value\": {\n" +
  975 + " \"userValue\": null,\n" +
  976 + " \"defaultValue\": 10,\n" +
  977 + " \"dynamicValue\": null\n" +
  978 + " },\n" +
  979 + " \"type\": \"NUMERIC\"\n" +
  980 + " },\n" +
  981 + " {\n" +
  982 + " \"type\": \"COMPLEX\",\n" +
  983 + " \"operation\": \"AND\",\n" +
  984 + " \"predicates\": [\n" +
  985 + " {\n" +
  986 + " \"operation\": \"GREATER\",\n" +
  987 + " \"value\": {\n" +
  988 + " \"userValue\": null,\n" +
  989 + " \"defaultValue\": 50,\n" +
  990 + " \"dynamicValue\": null\n" +
  991 + " },\n" +
  992 + " \"type\": \"NUMERIC\"\n" +
  993 + " },\n" +
  994 + " {\n" +
  995 + " \"operation\": \"LESS\",\n" +
  996 + " \"value\": {\n" +
  997 + " \"userValue\": null,\n" +
  998 + " \"defaultValue\": 60,\n" +
  999 + " \"dynamicValue\": null\n" +
  1000 + " },\n" +
  1001 + " \"type\": \"NUMERIC\"\n" +
  1002 + " }\n" +
  1003 + " ]\n" +
  1004 + " }\n" +
  1005 + " ]\n" +
  1006 + "}" +
  1007 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  1008 + "You may also want to replace hardcoded values (for example, temperature > 20) with the more dynamic " +
  1009 + "expression (for example, temperature > value of the tenant attribute with key 'temperatureThreshold'). " +
  1010 + "It is possible to use 'dynamicValue' to define attribute of the tenant, customer or device. " +
  1011 + "See example below:" + NEW_LINE +
  1012 + MARKDOWN_CODE_BLOCK_START +
  1013 + "{\n" +
  1014 + " \"operation\": \"GREATER\",\n" +
  1015 + " \"value\": {\n" +
  1016 + " \"userValue\": null,\n" +
  1017 + " \"defaultValue\": 0,\n" +
  1018 + " \"dynamicValue\": {\n" +
  1019 + " \"inherit\": false,\n" +
  1020 + " \"sourceType\": \"CURRENT_TENANT\",\n" +
  1021 + " \"sourceAttribute\": \"temperatureThreshold\"\n" +
  1022 + " }\n" +
  1023 + " },\n" +
  1024 + " \"type\": \"NUMERIC\"\n" +
  1025 + "}" +
  1026 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  1027 + "Note that you may use 'CURRENT_DEVICE', 'CURRENT_CUSTOMER' and 'CURRENT_TENANT' as a 'sourceType'. The 'defaultValue' is used when the attribute with such a name is not defined for the chosen source. " +
  1028 + "The 'sourceAttribute' can be inherited from the owner of the specified 'sourceType' if 'inherit' is set to true.";
  1029 +
  1030 + protected static final String KEY_FILTERS_DESCRIPTION = "# Key Filters" + NEW_LINE +
  1031 + "Key filter objects are created under the **'condition'** array. They allow you to define complex logical expressions over entity field, " +
  1032 + "attribute, latest time-series value or constant. The filter is defined using 'key', 'valueType', " +
  1033 + "'value' (refers to the value of the 'CONSTANT' alarm filter key type) and 'predicate' objects. Let's review each object:" + NEW_LINE +
  1034 + ALARM_FILTER_KEY + FILTER_VALUE_TYPE + NEW_LINE + DEVICE_PROFILE_FILTER_PREDICATE + NEW_LINE;
  1035 +
  1036 + protected static final String DEFAULT_DEVICE_PROFILE_DATA_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\n" +
  1037 + " \"alarms\":[\n" +
  1038 + " ],\n" +
  1039 + " \"configuration\":{\n" +
  1040 + " \"type\":\"DEFAULT\"\n" +
  1041 + " },\n" +
  1042 + " \"provisionConfiguration\":{\n" +
  1043 + " \"type\":\"DISABLED\",\n" +
  1044 + " \"provisionDeviceSecret\":null\n" +
  1045 + " },\n" +
  1046 + " \"transportConfiguration\":{\n" +
  1047 + " \"type\":\"DEFAULT\"\n" +
  1048 + " }\n" +
  1049 + "}" + MARKDOWN_CODE_BLOCK_END;
  1050 +
  1051 + protected static final String CUSTOM_DEVICE_PROFILE_DATA_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\n" +
  1052 + " \"alarms\":[\n" +
  1053 + " {\n" +
  1054 + " \"id\":\"2492b935-1226-59e9-8615-17d8978a4f93\",\n" +
  1055 + " \"alarmType\":\"Temperature Alarm\",\n" +
  1056 + " \"clearRule\":{\n" +
  1057 + " \"schedule\":null,\n" +
  1058 + " \"condition\":{\n" +
  1059 + " \"spec\":{\n" +
  1060 + " \"type\":\"SIMPLE\"\n" +
  1061 + " },\n" +
  1062 + " \"condition\":[\n" +
  1063 + " {\n" +
  1064 + " \"key\":{\n" +
  1065 + " \"key\":\"temperature\",\n" +
  1066 + " \"type\":\"TIME_SERIES\"\n" +
  1067 + " },\n" +
  1068 + " \"value\":null,\n" +
  1069 + " \"predicate\":{\n" +
  1070 + " \"type\":\"NUMERIC\",\n" +
  1071 + " \"value\":{\n" +
  1072 + " \"userValue\":null,\n" +
  1073 + " \"defaultValue\":30.0,\n" +
  1074 + " \"dynamicValue\":null\n" +
  1075 + " },\n" +
  1076 + " \"operation\":\"LESS\"\n" +
  1077 + " },\n" +
  1078 + " \"valueType\":\"NUMERIC\"\n" +
  1079 + " }\n" +
  1080 + " ]\n" +
  1081 + " },\n" +
  1082 + " \"dashboardId\":null,\n" +
  1083 + " \"alarmDetails\":null\n" +
  1084 + " },\n" +
  1085 + " \"propagate\":false,\n" +
  1086 + " \"createRules\":{\n" +
  1087 + " \"MAJOR\":{\n" +
  1088 + " \"schedule\":{\n" +
  1089 + " \"type\":\"SPECIFIC_TIME\",\n" +
  1090 + " \"endsOn\":64800000,\n" +
  1091 + " \"startsOn\":43200000,\n" +
  1092 + " \"timezone\":\"Europe/Kiev\",\n" +
  1093 + " \"daysOfWeek\":[\n" +
  1094 + " 1,\n" +
  1095 + " 3,\n" +
  1096 + " 5\n" +
  1097 + " ]\n" +
  1098 + " },\n" +
  1099 + " \"condition\":{\n" +
  1100 + " \"spec\":{\n" +
  1101 + " \"type\":\"DURATION\",\n" +
  1102 + " \"unit\":\"MINUTES\",\n" +
  1103 + " \"predicate\":{\n" +
  1104 + " \"userValue\":null,\n" +
  1105 + " \"defaultValue\":30,\n" +
  1106 + " \"dynamicValue\":null\n" +
  1107 + " }\n" +
  1108 + " },\n" +
  1109 + " \"condition\":[\n" +
  1110 + " {\n" +
  1111 + " \"key\":{\n" +
  1112 + " \"key\":\"temperature\",\n" +
  1113 + " \"type\":\"TIME_SERIES\"\n" +
  1114 + " },\n" +
  1115 + " \"value\":null,\n" +
  1116 + " \"predicate\":{\n" +
  1117 + " \"type\":\"COMPLEX\",\n" +
  1118 + " \"operation\":\"OR\",\n" +
  1119 + " \"predicates\":[\n" +
  1120 + " {\n" +
  1121 + " \"type\":\"NUMERIC\",\n" +
  1122 + " \"value\":{\n" +
  1123 + " \"userValue\":null,\n" +
  1124 + " \"defaultValue\":50.0,\n" +
  1125 + " \"dynamicValue\":null\n" +
  1126 + " },\n" +
  1127 + " \"operation\":\"LESS_OR_EQUAL\"\n" +
  1128 + " },\n" +
  1129 + " {\n" +
  1130 + " \"type\":\"NUMERIC\",\n" +
  1131 + " \"value\":{\n" +
  1132 + " \"userValue\":null,\n" +
  1133 + " \"defaultValue\":30.0,\n" +
  1134 + " \"dynamicValue\":null\n" +
  1135 + " },\n" +
  1136 + " \"operation\":\"GREATER\"\n" +
  1137 + " }\n" +
  1138 + " ]\n" +
  1139 + " },\n" +
  1140 + " \"valueType\":\"NUMERIC\"\n" +
  1141 + " }\n" +
  1142 + " ]\n" +
  1143 + " },\n" +
  1144 + " \"dashboardId\":null,\n" +
  1145 + " \"alarmDetails\":null\n" +
  1146 + " },\n" +
  1147 + " \"WARNING\":{\n" +
  1148 + " \"schedule\":{\n" +
  1149 + " \"type\":\"CUSTOM\",\n" +
  1150 + " \"items\":[\n" +
  1151 + " {\n" +
  1152 + " \"endsOn\":0,\n" +
  1153 + " \"enabled\":false,\n" +
  1154 + " \"startsOn\":0,\n" +
  1155 + " \"dayOfWeek\":1\n" +
  1156 + " },\n" +
  1157 + " {\n" +
  1158 + " \"endsOn\":64800000,\n" +
  1159 + " \"enabled\":true,\n" +
  1160 + " \"startsOn\":43200000,\n" +
  1161 + " \"dayOfWeek\":2\n" +
  1162 + " },\n" +
  1163 + " {\n" +
  1164 + " \"endsOn\":0,\n" +
  1165 + " \"enabled\":false,\n" +
  1166 + " \"startsOn\":0,\n" +
  1167 + " \"dayOfWeek\":3\n" +
  1168 + " },\n" +
  1169 + " {\n" +
  1170 + " \"endsOn\":57600000,\n" +
  1171 + " \"enabled\":true,\n" +
  1172 + " \"startsOn\":36000000,\n" +
  1173 + " \"dayOfWeek\":4\n" +
  1174 + " },\n" +
  1175 + " {\n" +
  1176 + " \"endsOn\":0,\n" +
  1177 + " \"enabled\":false,\n" +
  1178 + " \"startsOn\":0,\n" +
  1179 + " \"dayOfWeek\":5\n" +
  1180 + " },\n" +
  1181 + " {\n" +
  1182 + " \"endsOn\":0,\n" +
  1183 + " \"enabled\":false,\n" +
  1184 + " \"startsOn\":0,\n" +
  1185 + " \"dayOfWeek\":6\n" +
  1186 + " },\n" +
  1187 + " {\n" +
  1188 + " \"endsOn\":0,\n" +
  1189 + " \"enabled\":false,\n" +
  1190 + " \"startsOn\":0,\n" +
  1191 + " \"dayOfWeek\":7\n" +
  1192 + " }\n" +
  1193 + " ],\n" +
  1194 + " \"timezone\":\"Europe/Kiev\"\n" +
  1195 + " },\n" +
  1196 + " \"condition\":{\n" +
  1197 + " \"spec\":{\n" +
  1198 + " \"type\":\"REPEATING\",\n" +
  1199 + " \"predicate\":{\n" +
  1200 + " \"userValue\":null,\n" +
  1201 + " \"defaultValue\":5,\n" +
  1202 + " \"dynamicValue\":null\n" +
  1203 + " }\n" +
  1204 + " },\n" +
  1205 + " \"condition\":[\n" +
  1206 + " {\n" +
  1207 + " \"key\":{\n" +
  1208 + " \"key\":\"tempConstant\",\n" +
  1209 + " \"type\":\"CONSTANT\"\n" +
  1210 + " },\n" +
  1211 + " \"value\":30,\n" +
  1212 + " \"predicate\":{\n" +
  1213 + " \"type\":\"NUMERIC\",\n" +
  1214 + " \"value\":{\n" +
  1215 + " \"userValue\":null,\n" +
  1216 + " \"defaultValue\":0.0,\n" +
  1217 + " \"dynamicValue\":{\n" +
  1218 + " \"inherit\":false,\n" +
  1219 + " \"sourceType\":\"CURRENT_DEVICE\",\n" +
  1220 + " \"sourceAttribute\":\"tempThreshold\"\n" +
  1221 + " }\n" +
  1222 + " },\n" +
  1223 + " \"operation\":\"EQUAL\"\n" +
  1224 + " },\n" +
  1225 + " \"valueType\":\"NUMERIC\"\n" +
  1226 + " }\n" +
  1227 + " ]\n" +
  1228 + " },\n" +
  1229 + " \"dashboardId\":null,\n" +
  1230 + " \"alarmDetails\":null\n" +
  1231 + " },\n" +
  1232 + " \"CRITICAL\":{\n" +
  1233 + " \"schedule\":null,\n" +
  1234 + " \"condition\":{\n" +
  1235 + " \"spec\":{\n" +
  1236 + " \"type\":\"SIMPLE\"\n" +
  1237 + " },\n" +
  1238 + " \"condition\":[\n" +
  1239 + " {\n" +
  1240 + " \"key\":{\n" +
  1241 + " \"key\":\"temperature\",\n" +
  1242 + " \"type\":\"TIME_SERIES\"\n" +
  1243 + " },\n" +
  1244 + " \"value\":null,\n" +
  1245 + " \"predicate\":{\n" +
  1246 + " \"type\":\"NUMERIC\",\n" +
  1247 + " \"value\":{\n" +
  1248 + " \"userValue\":null,\n" +
  1249 + " \"defaultValue\":50.0,\n" +
  1250 + " \"dynamicValue\":null\n" +
  1251 + " },\n" +
  1252 + " \"operation\":\"GREATER\"\n" +
  1253 + " },\n" +
  1254 + " \"valueType\":\"NUMERIC\"\n" +
  1255 + " }\n" +
  1256 + " ]\n" +
  1257 + " },\n" +
  1258 + " \"dashboardId\":null,\n" +
  1259 + " \"alarmDetails\":null\n" +
  1260 + " }\n" +
  1261 + " },\n" +
  1262 + " \"propagateRelationTypes\":null\n" +
  1263 + " }\n" +
  1264 + " ],\n" +
  1265 + " \"configuration\":{\n" +
  1266 + " \"type\":\"DEFAULT\"\n" +
  1267 + " },\n" +
  1268 + " \"provisionConfiguration\":{\n" +
  1269 + " \"type\":\"ALLOW_CREATE_NEW_DEVICES\",\n" +
  1270 + " \"provisionDeviceSecret\":\"vaxb9hzqdbz3oqukvomg\"\n" +
  1271 + " },\n" +
  1272 + " \"transportConfiguration\":{\n" +
  1273 + " \"type\":\"MQTT\",\n" +
  1274 + " \"deviceTelemetryTopic\":\"v1/devices/me/telemetry\",\n" +
  1275 + " \"deviceAttributesTopic\":\"v1/devices/me/attributes\",\n" +
  1276 + " \"transportPayloadTypeConfiguration\":{\n" +
  1277 + " \"transportPayloadType\":\"PROTOBUF\",\n" +
  1278 + " \"deviceTelemetryProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage telemetry;\\n\\nmessage SensorDataReading {\\n\\n optional double temperature = 1;\\n optional double humidity = 2;\\n InnerObject innerObject = 3;\\n\\n message InnerObject {\\n optional string key1 = 1;\\n optional bool key2 = 2;\\n optional double key3 = 3;\\n optional int32 key4 = 4;\\n optional string key5 = 5;\\n }\\n}\",\n" +
  1279 + " \"deviceAttributesProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage attributes;\\n\\nmessage SensorConfiguration {\\n optional string firmwareVersion = 1;\\n optional string serialNumber = 2;\\n}\",\n" +
  1280 + " \"deviceRpcRequestProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage rpc;\\n\\nmessage RpcRequestMsg {\\n optional string method = 1;\\n optional int32 requestId = 2;\\n optional string params = 3;\\n}\",\n" +
  1281 + " \"deviceRpcResponseProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage rpc;\\n\\nmessage RpcResponseMsg {\\n optional string payload = 1;\\n}\"\n" +
  1282 + " }\n" +
  1283 + " }\n" +
  1284 + "}" + MARKDOWN_CODE_BLOCK_END;
  1285 + protected static final String DEVICE_PROFILE_DATA_DEFINITION = NEW_LINE + "# Device profile data definition" + NEW_LINE +
  1286 + "Device profile data object contains alarm rules configuration, device provision strategy and transport type configuration for device connectivity. Let's review some examples. " +
  1287 + "First one is the default device profile data configuration and second one - the custom one. " +
  1288 + NEW_LINE + DEFAULT_DEVICE_PROFILE_DATA_EXAMPLE + NEW_LINE + CUSTOM_DEVICE_PROFILE_DATA_EXAMPLE +
  1289 + NEW_LINE + "Let's review some specific objects examples related to the device profile configuration:";
  1290 +
  1291 + protected static final String ALARM_SCHEDULE = NEW_LINE + "# Alarm Schedule" + NEW_LINE +
  1292 + "Alarm Schedule JSON object represents the time interval during which the alarm rule is active. Note, " +
  1293 + NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE + NEW_LINE + "means alarm rule is active all the time. " +
  1294 + "**'daysOfWeek'** field represents Monday as 1, Tuesday as 2 and so on. **'startsOn'** and **'endsOn'** fields represent hours in millis (e.g. 64800000 = 18:00 or 6pm). " +
  1295 + "**'enabled'** flag specifies if item in a custom rule is active for specific day of the week:" + NEW_LINE +
  1296 + "## Specific Time Schedule" + NEW_LINE +
  1297 + DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE + NEW_LINE +
  1298 + "## Custom Schedule" +
  1299 + NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE + NEW_LINE;
  1300 +
  1301 + protected static final String ALARM_CONDITION_TYPE = "# Alarm condition type (**'spec'**)" + NEW_LINE +
  1302 + "Alarm condition type can be either simple, duration, or repeating. For example, 5 times in a row or during 5 minutes." + NEW_LINE +
  1303 + "Note, **'userValue'** field is not used and reserved for future usage, **'dynamicValue'** is used for condition appliance by using the value of the **'sourceAttribute'** " +
  1304 + "or else **'defaultValue'** is used (if **'sourceAttribute'** is absent).\n" +
  1305 + "\n**'sourceType'** of the **'sourceAttribute'** can be: \n" +
  1306 + " * 'CURRENT_DEVICE';\n" +
  1307 + " * 'CURRENT_CUSTOMER';\n" +
  1308 + " * 'CURRENT_TENANT'." + NEW_LINE +
  1309 + "**'sourceAttribute'** can be inherited from the owner if **'inherit'** is set to true (for CURRENT_DEVICE and CURRENT_CUSTOMER)." + NEW_LINE +
  1310 + "## Repeating alarm condition" + NEW_LINE +
  1311 + DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE + NEW_LINE +
  1312 + "## Duration alarm condition" + NEW_LINE +
  1313 + DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE + NEW_LINE +
  1314 + "**'unit'** can be: \n" +
  1315 + " * 'SECONDS';\n" +
  1316 + " * 'MINUTES';\n" +
  1317 + " * 'HOURS';\n" +
  1318 + " * 'DAYS'." + NEW_LINE;
  1319 +
  1320 + protected static final String PROVISION_CONFIGURATION = "# Provision Configuration" + NEW_LINE +
  1321 + "There are 3 types of device provision configuration for the device profile: \n" +
  1322 + " * 'DISABLED';\n" +
  1323 + " * 'ALLOW_CREATE_NEW_DEVICES';\n" +
  1324 + " * 'CHECK_PRE_PROVISIONED_DEVICES'." + NEW_LINE +
  1325 + "Please refer to the [docs](https://thingsboard.io/docs/user-guide/device-provisioning/) for more details." + NEW_LINE;
  1326 +
  1327 + protected static final String DEVICE_PROFILE_DATA = DEVICE_PROFILE_DATA_DEFINITION + ALARM_SCHEDULE + ALARM_CONDITION_TYPE +
  1328 + KEY_FILTERS_DESCRIPTION + PROVISION_CONFIGURATION + TRANSPORT_CONFIGURATION;
  1329 +
  1330 + protected static final String DEVICE_PROFILE_ID = "deviceProfileId";
  1331 +
  1332 +}
@@ -47,6 +47,20 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -47,6 +47,20 @@ import org.thingsboard.server.service.security.permission.Resource;
47 47
48 import java.util.List; 48 import java.util.List;
49 49
  50 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID;
  51 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
  52 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES;
  53 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_TEXT_SEARCH_DESCRIPTION;
  54 +import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD;
  55 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  56 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  57 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  58 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  59 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  60 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  61 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  62 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  63 +
50 @RestController 64 @RestController
51 @TbCoreComponent 65 @TbCoreComponent
52 @RequestMapping("/api") 66 @RequestMapping("/api")
@@ -57,7 +71,8 @@ public class CustomerController extends BaseController { @@ -57,7 +71,8 @@ public class CustomerController extends BaseController {
57 "If the user has the authority of 'Customer User', the server checks that the user belongs to the customer."; 71 "If the user has the authority of 'Customer User', the server checks that the user belongs to the customer.";
58 72
59 @ApiOperation(value = "Get Customer (getCustomerById)", 73 @ApiOperation(value = "Get Customer (getCustomerById)",
60 - notes = "Get the Customer object based on the provided Customer Id. " + CUSTOMER_SECURITY_CHECK) 74 + notes = "Get the Customer object based on the provided Customer Id. "
  75 + + CUSTOMER_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
61 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 76 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
62 @RequestMapping(value = "/customer/{customerId}", method = RequestMethod.GET) 77 @RequestMapping(value = "/customer/{customerId}", method = RequestMethod.GET)
63 @ResponseBody 78 @ResponseBody
@@ -79,7 +94,8 @@ public class CustomerController extends BaseController { @@ -79,7 +94,8 @@ public class CustomerController extends BaseController {
79 94
80 95
81 @ApiOperation(value = "Get short Customer info (getShortCustomerInfoById)", 96 @ApiOperation(value = "Get short Customer info (getShortCustomerInfoById)",
82 - notes = "Get the short customer object that contains only the title and 'isPublic' flag. " + CUSTOMER_SECURITY_CHECK) 97 + notes = "Get the short customer object that contains only the title and 'isPublic' flag. "
  98 + + CUSTOMER_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
83 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 99 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
84 @RequestMapping(value = "/customer/{customerId}/shortInfo", method = RequestMethod.GET) 100 @RequestMapping(value = "/customer/{customerId}/shortInfo", method = RequestMethod.GET)
85 @ResponseBody 101 @ResponseBody
@@ -101,7 +117,8 @@ public class CustomerController extends BaseController { @@ -101,7 +117,8 @@ public class CustomerController extends BaseController {
101 } 117 }
102 118
103 @ApiOperation(value = "Get Customer Title (getCustomerTitleById)", 119 @ApiOperation(value = "Get Customer Title (getCustomerTitleById)",
104 - notes = "Get the title of the customer. " + CUSTOMER_SECURITY_CHECK) 120 + notes = "Get the title of the customer. "
  121 + + CUSTOMER_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
105 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 122 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
106 @RequestMapping(value = "/customer/{customerId}/title", method = RequestMethod.GET, produces = "application/text") 123 @RequestMapping(value = "/customer/{customerId}/title", method = RequestMethod.GET, produces = "application/text")
107 @ResponseBody 124 @ResponseBody
@@ -122,7 +139,7 @@ public class CustomerController extends BaseController { @@ -122,7 +139,7 @@ public class CustomerController extends BaseController {
122 notes = "Creates or Updates the Customer. When creating customer, platform generates Customer Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) " + 139 notes = "Creates or Updates the Customer. When creating customer, platform generates Customer Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) " +
123 "The newly created Customer Id will be present in the response. " + 140 "The newly created Customer Id will be present in the response. " +
124 "Specify existing Customer Id to update the Customer. " + 141 "Specify existing Customer Id to update the Customer. " +
125 - "Referencing non-existing Customer Id will cause 'Not Found' error.") 142 + "Referencing non-existing Customer Id will cause 'Not Found' error." + TENANT_AUTHORITY_PARAGRAPH)
126 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 143 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
127 @RequestMapping(value = "/customer", method = RequestMethod.POST) 144 @RequestMapping(value = "/customer", method = RequestMethod.POST)
128 @ResponseBody 145 @ResponseBody
@@ -153,7 +170,9 @@ public class CustomerController extends BaseController { @@ -153,7 +170,9 @@ public class CustomerController extends BaseController {
153 } 170 }
154 171
155 @ApiOperation(value = "Delete Customer (deleteCustomer)", 172 @ApiOperation(value = "Delete Customer (deleteCustomer)",
156 - notes = "Deletes the Customer and all customer Users. All assigned Dashboards, Assets, Devices, etc. will be unassigned but not deleted. Referencing non-existing Customer Id will cause an error.") 173 + notes = "Deletes the Customer and all customer Users. " +
  174 + "All assigned Dashboards, Assets, Devices, etc. will be unassigned but not deleted. " +
  175 + "Referencing non-existing Customer Id will cause an error." + TENANT_AUTHORITY_PARAGRAPH)
157 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 176 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
158 @RequestMapping(value = "/customer/{customerId}", method = RequestMethod.DELETE) 177 @RequestMapping(value = "/customer/{customerId}", method = RequestMethod.DELETE)
159 @ResponseStatus(value = HttpStatus.OK) 178 @ResponseStatus(value = HttpStatus.OK)
@@ -187,7 +206,7 @@ public class CustomerController extends BaseController { @@ -187,7 +206,7 @@ public class CustomerController extends BaseController {
187 206
188 @ApiOperation(value = "Get Tenant Customers (getCustomers)", 207 @ApiOperation(value = "Get Tenant Customers (getCustomers)",
189 notes = "Returns a page of customers owned by tenant. " + 208 notes = "Returns a page of customers owned by tenant. " +
190 - PAGE_DATA_PARAMETERS) 209 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
191 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 210 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
192 @RequestMapping(value = "/customers", params = {"pageSize", "page"}, method = RequestMethod.GET) 211 @RequestMapping(value = "/customers", params = {"pageSize", "page"}, method = RequestMethod.GET)
193 @ResponseBody 212 @ResponseBody
@@ -212,7 +231,7 @@ public class CustomerController extends BaseController { @@ -212,7 +231,7 @@ public class CustomerController extends BaseController {
212 } 231 }
213 232
214 @ApiOperation(value = "Get Tenant Customer by Customer title (getTenantCustomer)", 233 @ApiOperation(value = "Get Tenant Customer by Customer title (getTenantCustomer)",
215 - notes = "Get the Customer using Customer Title. " + ADMINISTRATOR_AUTHORITY_ONLY) 234 + notes = "Get the Customer using Customer Title. " + TENANT_AUTHORITY_PARAGRAPH)
216 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 235 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
217 @RequestMapping(value = "/tenant/customers", params = {"customerTitle"}, method = RequestMethod.GET) 236 @RequestMapping(value = "/tenant/customers", params = {"customerTitle"}, method = RequestMethod.GET)
218 @ResponseBody 237 @ResponseBody
@@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam;
31 import org.springframework.web.bind.annotation.ResponseBody; 31 import org.springframework.web.bind.annotation.ResponseBody;
32 import org.springframework.web.bind.annotation.ResponseStatus; 32 import org.springframework.web.bind.annotation.ResponseStatus;
33 import org.springframework.web.bind.annotation.RestController; 33 import org.springframework.web.bind.annotation.RestController;
  34 +import org.thingsboard.common.util.JacksonUtil;
34 import org.thingsboard.server.common.data.Customer; 35 import org.thingsboard.server.common.data.Customer;
35 import org.thingsboard.server.common.data.Dashboard; 36 import org.thingsboard.server.common.data.Dashboard;
36 import org.thingsboard.server.common.data.DashboardInfo; 37 import org.thingsboard.server.common.data.DashboardInfo;
@@ -50,7 +51,6 @@ import org.thingsboard.server.common.data.id.EdgeId; @@ -50,7 +51,6 @@ import org.thingsboard.server.common.data.id.EdgeId;
50 import org.thingsboard.server.common.data.id.TenantId; 51 import org.thingsboard.server.common.data.id.TenantId;
51 import org.thingsboard.server.common.data.page.PageData; 52 import org.thingsboard.server.common.data.page.PageData;
52 import org.thingsboard.server.common.data.page.PageLink; 53 import org.thingsboard.server.common.data.page.PageLink;
53 -import org.thingsboard.common.util.JacksonUtil;  
54 import org.thingsboard.server.common.data.page.TimePageLink; 54 import org.thingsboard.server.common.data.page.TimePageLink;
55 import org.thingsboard.server.queue.util.TbCoreComponent; 55 import org.thingsboard.server.queue.util.TbCoreComponent;
56 import org.thingsboard.server.service.security.model.SecurityUser; 56 import org.thingsboard.server.service.security.model.SecurityUser;
@@ -62,6 +62,27 @@ import java.util.List; @@ -62,6 +62,27 @@ import java.util.List;
62 import java.util.Set; 62 import java.util.Set;
63 import java.util.stream.Collectors; 63 import java.util.stream.Collectors;
64 64
  65 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID;
  66 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
  67 +import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_ID_PARAM_DESCRIPTION;
  68 +import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES;
  69 +import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_TEXT_SEARCH_DESCRIPTION;
  70 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  71 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
  72 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  73 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
  74 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  75 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  76 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  77 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  78 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  79 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  80 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
  81 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  82 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID;
  83 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION;
  84 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  85 +
65 @RestController 86 @RestController
66 @TbCoreComponent 87 @TbCoreComponent
67 @RequestMapping("/api") 88 @RequestMapping("/api")
@@ -120,7 +141,7 @@ public class DashboardController extends BaseController { @@ -120,7 +141,7 @@ public class DashboardController extends BaseController {
120 } 141 }
121 142
122 @ApiOperation(value = "Get Dashboard (getDashboardById)", 143 @ApiOperation(value = "Get Dashboard (getDashboardById)",
123 - notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION, 144 + notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
124 produces = MediaType.APPLICATION_JSON_VALUE 145 produces = MediaType.APPLICATION_JSON_VALUE
125 ) 146 )
126 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 147 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@@ -143,7 +164,7 @@ public class DashboardController extends BaseController { @@ -143,7 +164,7 @@ public class DashboardController extends BaseController {
143 "The newly created Dashboard id will be present in the response. " + 164 "The newly created Dashboard id will be present in the response. " +
144 "Specify existing Dashboard id to update the dashboard. " + 165 "Specify existing Dashboard id to update the dashboard. " +
145 "Referencing non-existing dashboard Id will cause 'Not Found' error. " + 166 "Referencing non-existing dashboard Id will cause 'Not Found' error. " +
146 - "Only users with 'TENANT_ADMIN') authority may create the dashboards.", 167 + TENANT_AUTHORITY_PARAGRAPH,
147 produces = MediaType.APPLICATION_JSON_VALUE, 168 produces = MediaType.APPLICATION_JSON_VALUE,
148 consumes = MediaType.APPLICATION_JSON_VALUE) 169 consumes = MediaType.APPLICATION_JSON_VALUE)
149 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 170 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@@ -177,7 +198,7 @@ public class DashboardController extends BaseController { @@ -177,7 +198,7 @@ public class DashboardController extends BaseController {
177 } 198 }
178 199
179 @ApiOperation(value = "Delete the Dashboard (deleteDashboard)", 200 @ApiOperation(value = "Delete the Dashboard (deleteDashboard)",
180 - notes = "Delete the Dashboard. Only users with 'TENANT_ADMIN') authority may delete the dashboards.") 201 + notes = "Delete the Dashboard." + TENANT_AUTHORITY_PARAGRAPH)
181 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 202 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
182 @RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.DELETE) 203 @RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.DELETE)
183 @ResponseStatus(value = HttpStatus.OK) 204 @ResponseStatus(value = HttpStatus.OK)
@@ -211,7 +232,7 @@ public class DashboardController extends BaseController { @@ -211,7 +232,7 @@ public class DashboardController extends BaseController {
211 232
212 @ApiOperation(value = "Assign the Dashboard (assignDashboardToCustomer)", 233 @ApiOperation(value = "Assign the Dashboard (assignDashboardToCustomer)",
213 notes = "Assign the Dashboard to specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + 234 notes = "Assign the Dashboard to specified Customer or do nothing if the Dashboard is already assigned to that Customer. " +
214 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.", 235 + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH,
215 produces = MediaType.APPLICATION_JSON_VALUE) 236 produces = MediaType.APPLICATION_JSON_VALUE)
216 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 237 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
217 @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST) 238 @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST)
@@ -251,7 +272,7 @@ public class DashboardController extends BaseController { @@ -251,7 +272,7 @@ public class DashboardController extends BaseController {
251 272
252 @ApiOperation(value = "Unassign the Dashboard (unassignDashboardFromCustomer)", 273 @ApiOperation(value = "Unassign the Dashboard (unassignDashboardFromCustomer)",
253 notes = "Unassign the Dashboard from specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + 274 notes = "Unassign the Dashboard from specified Customer or do nothing if the Dashboard is already assigned to that Customer. " +
254 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may unassign the dashboards from customers.", 275 + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH,
255 produces = MediaType.APPLICATION_JSON_VALUE) 276 produces = MediaType.APPLICATION_JSON_VALUE)
256 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 277 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
257 @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) 278 @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@@ -290,7 +311,7 @@ public class DashboardController extends BaseController { @@ -290,7 +311,7 @@ public class DashboardController extends BaseController {
290 311
291 @ApiOperation(value = "Update the Dashboard Customers (updateDashboardCustomers)", 312 @ApiOperation(value = "Update the Dashboard Customers (updateDashboardCustomers)",
292 notes = "Updates the list of Customers that this Dashboard is assigned to. Removes previous assignments to customers that are not in the provided list. " + 313 notes = "Updates the list of Customers that this Dashboard is assigned to. Removes previous assignments to customers that are not in the provided list. " +
293 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.", 314 + "Returns the Dashboard object. " + TENANT_AUTHORITY_PARAGRAPH,
294 produces = MediaType.APPLICATION_JSON_VALUE, 315 produces = MediaType.APPLICATION_JSON_VALUE,
295 consumes = MediaType.APPLICATION_JSON_VALUE) 316 consumes = MediaType.APPLICATION_JSON_VALUE)
296 317
@@ -365,7 +386,7 @@ public class DashboardController extends BaseController { @@ -365,7 +386,7 @@ public class DashboardController extends BaseController {
365 386
366 @ApiOperation(value = "Adds the Dashboard Customers (addDashboardCustomers)", 387 @ApiOperation(value = "Adds the Dashboard Customers (addDashboardCustomers)",
367 notes = "Adds the list of Customers to the existing list of assignments for the Dashboard. Keeps previous assignments to customers that are not in the provided list. " + 388 notes = "Adds the list of Customers to the existing list of assignments for the Dashboard. Keeps previous assignments to customers that are not in the provided list. " +
368 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.", 389 + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH,
369 produces = MediaType.APPLICATION_JSON_VALUE, 390 produces = MediaType.APPLICATION_JSON_VALUE,
370 consumes = MediaType.APPLICATION_JSON_VALUE) 391 consumes = MediaType.APPLICATION_JSON_VALUE)
371 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 392 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@@ -417,7 +438,7 @@ public class DashboardController extends BaseController { @@ -417,7 +438,7 @@ public class DashboardController extends BaseController {
417 438
418 @ApiOperation(value = "Remove the Dashboard Customers (removeDashboardCustomers)", 439 @ApiOperation(value = "Remove the Dashboard Customers (removeDashboardCustomers)",
419 notes = "Removes the list of Customers from the existing list of assignments for the Dashboard. Keeps other assignments to customers that are not in the provided list. " + 440 notes = "Removes the list of Customers from the existing list of assignments for the Dashboard. Keeps other assignments to customers that are not in the provided list. " +
420 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.", 441 + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH,
421 produces = MediaType.APPLICATION_JSON_VALUE, 442 produces = MediaType.APPLICATION_JSON_VALUE,
422 consumes = MediaType.APPLICATION_JSON_VALUE) 443 consumes = MediaType.APPLICATION_JSON_VALUE)
423 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 444 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@@ -473,7 +494,7 @@ public class DashboardController extends BaseController { @@ -473,7 +494,7 @@ public class DashboardController extends BaseController {
473 "Be aware that making the dashboard public does not mean that it automatically makes all devices and assets you use in the dashboard to be public." + 494 "Be aware that making the dashboard public does not mean that it automatically makes all devices and assets you use in the dashboard to be public." +
474 "Use [assign Asset to Public Customer](#!/asset-controller/assignAssetToPublicCustomerUsingPOST) and " + 495 "Use [assign Asset to Public Customer](#!/asset-controller/assignAssetToPublicCustomerUsingPOST) and " +
475 "[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " + 496 "[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " +
476 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.", 497 + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH,
477 produces = MediaType.APPLICATION_JSON_VALUE) 498 produces = MediaType.APPLICATION_JSON_VALUE)
478 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 499 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
479 @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST) 500 @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST)
@@ -505,7 +526,7 @@ public class DashboardController extends BaseController { @@ -505,7 +526,7 @@ public class DashboardController extends BaseController {
505 526
506 @ApiOperation(value = "Unassign the Dashboard from Public Customer (unassignDashboardFromPublicCustomer)", 527 @ApiOperation(value = "Unassign the Dashboard from Public Customer (unassignDashboardFromPublicCustomer)",
507 notes = "Unassigns the dashboard from a special, auto-generated 'Public' Customer. Once unassigned, unauthenticated users may no longer browse the dashboard. " + 528 notes = "Unassigns the dashboard from a special, auto-generated 'Public' Customer. Once unassigned, unauthenticated users may no longer browse the dashboard. " +
508 - "Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.", 529 + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH,
509 produces = MediaType.APPLICATION_JSON_VALUE) 530 produces = MediaType.APPLICATION_JSON_VALUE)
510 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 531 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
511 @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE) 532 @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@@ -538,7 +559,7 @@ public class DashboardController extends BaseController { @@ -538,7 +559,7 @@ public class DashboardController extends BaseController {
538 559
539 @ApiOperation(value = "Get Tenant Dashboards by System Administrator (getTenantDashboards)", 560 @ApiOperation(value = "Get Tenant Dashboards by System Administrator (getTenantDashboards)",
540 notes = "Returns a page of dashboard info objects owned by tenant. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + 561 notes = "Returns a page of dashboard info objects owned by tenant. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS +
541 - "Only users with 'SYS_ADMIN' authority may use this method.", 562 + SYSTEM_AUTHORITY_PARAGRAPH,
542 produces = MediaType.APPLICATION_JSON_VALUE) 563 produces = MediaType.APPLICATION_JSON_VALUE)
543 @PreAuthorize("hasAuthority('SYS_ADMIN')") 564 @PreAuthorize("hasAuthority('SYS_ADMIN')")
544 @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) 565 @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -567,8 +588,8 @@ public class DashboardController extends BaseController { @@ -567,8 +588,8 @@ public class DashboardController extends BaseController {
567 } 588 }
568 589
569 @ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)", 590 @ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)",
570 - notes = "Returns a page of dashboard info objects owned by the tenant of a current user. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS +  
571 - "Only users with 'TENANT_ADMIN' authority may use this method.", 591 + notes = "Returns a page of dashboard info objects owned by the tenant of a current user. "
  592 + + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH,
572 produces = MediaType.APPLICATION_JSON_VALUE) 593 produces = MediaType.APPLICATION_JSON_VALUE)
573 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 594 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
574 @RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) 595 @RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -600,8 +621,8 @@ public class DashboardController extends BaseController { @@ -600,8 +621,8 @@ public class DashboardController extends BaseController {
600 } 621 }
601 622
602 @ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)", 623 @ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)",
603 - notes = "Returns a page of dashboard info objects owned by the specified customer. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS +  
604 - "Only users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority may use this method.", 624 + notes = "Returns a page of dashboard info objects owned by the specified customer. "
  625 + + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
605 produces = MediaType.APPLICATION_JSON_VALUE) 626 produces = MediaType.APPLICATION_JSON_VALUE)
606 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 627 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
607 @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) 628 @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -641,8 +662,7 @@ public class DashboardController extends BaseController { @@ -641,8 +662,7 @@ public class DashboardController extends BaseController {
641 notes = "Returns the home dashboard object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " + 662 notes = "Returns the home dashboard object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " +
642 "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + 663 "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " +
643 "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " 664 "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. "
644 - + DASHBOARD_DEFINITION + " " +  
645 - "Only users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority should use this method.", 665 + + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
646 produces = MediaType.APPLICATION_JSON_VALUE) 666 produces = MediaType.APPLICATION_JSON_VALUE)
647 @PreAuthorize("isAuthenticated()") 667 @PreAuthorize("isAuthenticated()")
648 @RequestMapping(value = "/dashboard/home", method = RequestMethod.GET) 668 @RequestMapping(value = "/dashboard/home", method = RequestMethod.GET)
@@ -679,7 +699,7 @@ public class DashboardController extends BaseController { @@ -679,7 +699,7 @@ public class DashboardController extends BaseController {
679 notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " + 699 notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " +
680 "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + 700 "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " +
681 "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " + 701 "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " +
682 - "Only users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority should use this method.", 702 + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
683 produces = MediaType.APPLICATION_JSON_VALUE) 703 produces = MediaType.APPLICATION_JSON_VALUE)
684 @PreAuthorize("isAuthenticated()") 704 @PreAuthorize("isAuthenticated()")
685 @RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET) 705 @RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET)
@@ -714,7 +734,7 @@ public class DashboardController extends BaseController { @@ -714,7 +734,7 @@ public class DashboardController extends BaseController {
714 734
715 @ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", 735 @ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
716 notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the corresponding tenant. " + 736 notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the corresponding tenant. " +
717 - "Only users with 'TENANT_ADMIN' authority may use this method.", 737 + TENANT_AUTHORITY_PARAGRAPH,
718 produces = MediaType.APPLICATION_JSON_VALUE) 738 produces = MediaType.APPLICATION_JSON_VALUE)
719 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 739 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
720 @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET) 740 @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET)
@@ -740,7 +760,7 @@ public class DashboardController extends BaseController { @@ -740,7 +760,7 @@ public class DashboardController extends BaseController {
740 760
741 @ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", 761 @ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
742 notes = "Update the home dashboard assignment for the current tenant. " + 762 notes = "Update the home dashboard assignment for the current tenant. " +
743 - "Only users with 'TENANT_ADMIN' authority may use this method.", 763 + TENANT_AUTHORITY_PARAGRAPH,
744 produces = MediaType.APPLICATION_JSON_VALUE) 764 produces = MediaType.APPLICATION_JSON_VALUE)
745 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 765 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
746 @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST) 766 @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST)
@@ -810,7 +830,8 @@ public class DashboardController extends BaseController { @@ -810,7 +830,8 @@ public class DashboardController extends BaseController {
810 EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + 830 EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
811 "Second, remote edge service will receive a copy of assignment dashboard " + 831 "Second, remote edge service will receive a copy of assignment dashboard " +
812 EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + ". " + 832 EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + ". " +
813 - "Third, once dashboard will be delivered to edge service, it's going to be available for usage on remote edge instance.", 833 + "Third, once dashboard will be delivered to edge service, it's going to be available for usage on remote edge instance." +
  834 + TENANT_AUTHORITY_PARAGRAPH,
814 produces = MediaType.APPLICATION_JSON_VALUE) 835 produces = MediaType.APPLICATION_JSON_VALUE)
815 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 836 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
816 @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.POST) 837 @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.POST)
@@ -850,7 +871,8 @@ public class DashboardController extends BaseController { @@ -850,7 +871,8 @@ public class DashboardController extends BaseController {
850 EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + 871 EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
851 "Second, remote edge service will receive an 'unassign' command to remove dashboard " + 872 "Second, remote edge service will receive an 'unassign' command to remove dashboard " +
852 EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + ". " + 873 EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + ". " +
853 - "Third, once 'unassign' command will be delivered to edge service, it's going to remove dashboard locally.", 874 + "Third, once 'unassign' command will be delivered to edge service, it's going to remove dashboard locally." +
  875 + TENANT_AUTHORITY_PARAGRAPH,
854 produces = MediaType.APPLICATION_JSON_VALUE) 876 produces = MediaType.APPLICATION_JSON_VALUE)
855 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 877 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
856 @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) 878 @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@@ -86,6 +86,29 @@ import java.util.List; @@ -86,6 +86,29 @@ import java.util.List;
86 import java.util.UUID; 86 import java.util.UUID;
87 import java.util.stream.Collectors; 87 import java.util.stream.Collectors;
88 88
  89 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH;
  90 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
  91 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION;
  92 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_INFO_DESCRIPTION;
  93 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_NAME_DESCRIPTION;
  94 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID_PARAM_DESCRIPTION;
  95 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES;
  96 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TEXT_SEARCH_DESCRIPTION;
  97 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TYPE_DESCRIPTION;
  98 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  99 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
  100 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION;
  101 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  102 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
  103 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  104 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  105 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  106 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  107 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  108 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  109 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  110 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION;
  111 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
89 import static org.thingsboard.server.controller.EdgeController.EDGE_ID; 112 import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
90 113
91 @RestController 114 @RestController
@@ -104,7 +127,8 @@ public class DeviceController extends BaseController { @@ -104,7 +127,8 @@ public class DeviceController extends BaseController {
104 @ApiOperation(value = "Get Device (getDeviceById)", 127 @ApiOperation(value = "Get Device (getDeviceById)",
105 notes = "Fetch the Device object based on the provided Device Id. " + 128 notes = "Fetch the Device object based on the provided Device Id. " +
106 "If the user has the authority of 'TENANT_ADMIN', the server checks that the device is owned by the same tenant. " + 129 "If the user has the authority of 'TENANT_ADMIN', the server checks that the device is owned by the same tenant. " +
107 - "If the user has the authority of 'CUSTOMER_USER', the server checks that the device is assigned to the same customer.") 130 + "If the user has the authority of 'CUSTOMER_USER', the server checks that the device is assigned to the same customer." +
  131 + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
108 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 132 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
109 @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) 133 @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET)
110 @ResponseBody 134 @ResponseBody
@@ -122,7 +146,8 @@ public class DeviceController extends BaseController { @@ -122,7 +146,8 @@ public class DeviceController extends BaseController {
122 @ApiOperation(value = "Get Device Info (getDeviceInfoById)", 146 @ApiOperation(value = "Get Device Info (getDeviceInfoById)",
123 notes = "Fetch the Device Info object based on the provided Device Id. " + 147 notes = "Fetch the Device Info object based on the provided Device Id. " +
124 "If the user has the authority of 'Tenant Administrator', the server checks that the device is owned by the same tenant. " + 148 "If the user has the authority of 'Tenant Administrator', the server checks that the device is owned by the same tenant. " +
125 - "If the user has the authority of 'Customer User', the server checks that the device is assigned to the same customer. " + DEVICE_INFO_DESCRIPTION) 149 + "If the user has the authority of 'Customer User', the server checks that the device is assigned to the same customer. " +
  150 + DEVICE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
126 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 151 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
127 @RequestMapping(value = "/device/info/{deviceId}", method = RequestMethod.GET) 152 @RequestMapping(value = "/device/info/{deviceId}", method = RequestMethod.GET)
128 @ResponseBody 153 @ResponseBody
@@ -139,11 +164,12 @@ public class DeviceController extends BaseController { @@ -139,11 +164,12 @@ public class DeviceController extends BaseController {
139 164
140 @ApiOperation(value = "Create Or Update Device (saveDevice)", 165 @ApiOperation(value = "Create Or Update Device (saveDevice)",
141 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). " + 166 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). " +
142 - "Device credentials are also generated if not provided in the 'accessToken' request parameter. " +  
143 - "The newly created device id will be present in the response. " +  
144 - "Specify existing Device id to update the device. " +  
145 - "Referencing non-existing device Id will cause 'Not Found' error." +  
146 - "\n\nDevice name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the device names and non-unique 'label' field for user-friendly visualization purposes.") 167 + "Device credentials are also generated if not provided in the 'accessToken' request parameter. " +
  168 + "The newly created device id will be present in the response. " +
  169 + "Specify existing Device id to update the device. " +
  170 + "Referencing non-existing device Id will cause 'Not Found' error." +
  171 + "\n\nDevice name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the device names and non-unique 'label' field for user-friendly visualization purposes."
  172 + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
147 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 173 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
148 @RequestMapping(value = "/device", method = RequestMethod.POST) 174 @RequestMapping(value = "/device", method = RequestMethod.POST)
149 @ResponseBody 175 @ResponseBody
@@ -187,7 +213,7 @@ public class DeviceController extends BaseController { @@ -187,7 +213,7 @@ public class DeviceController extends BaseController {
187 } 213 }
188 214
189 @ApiOperation(value = "Delete device (deleteDevice)", 215 @ApiOperation(value = "Delete device (deleteDevice)",
190 - notes = "Deletes the device, it's credentials and all the relations (from and to the device). Referencing non-existing device Id will cause an error.") 216 + notes = "Deletes the device, it's credentials and all the relations (from and to the device). Referencing non-existing device Id will cause an error." + TENANT_AUTHORITY_PARAGRAPH)
191 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 217 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
192 @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE) 218 @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE)
193 @ResponseStatus(value = HttpStatus.OK) 219 @ResponseStatus(value = HttpStatus.OK)
@@ -219,7 +245,7 @@ public class DeviceController extends BaseController { @@ -219,7 +245,7 @@ public class DeviceController extends BaseController {
219 } 245 }
220 246
221 @ApiOperation(value = "Assign device to customer (assignDeviceToCustomer)", 247 @ApiOperation(value = "Assign device to customer (assignDeviceToCustomer)",
222 - notes = "Creates assignment of the device to customer. Customer will be able to query device afterwards.") 248 + notes = "Creates assignment of the device to customer. Customer will be able to query device afterwards." + TENANT_AUTHORITY_PARAGRAPH)
223 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 249 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
224 @RequestMapping(value = "/customer/{customerId}/device/{deviceId}", method = RequestMethod.POST) 250 @RequestMapping(value = "/customer/{customerId}/device/{deviceId}", method = RequestMethod.POST)
225 @ResponseBody 251 @ResponseBody
@@ -255,7 +281,7 @@ public class DeviceController extends BaseController { @@ -255,7 +281,7 @@ public class DeviceController extends BaseController {
255 } 281 }
256 282
257 @ApiOperation(value = "Unassign device from customer (unassignDeviceFromCustomer)", 283 @ApiOperation(value = "Unassign device from customer (unassignDeviceFromCustomer)",
258 - notes = "Clears assignment of the device to customer. Customer will not be able to query device afterwards.") 284 + notes = "Clears assignment of the device to customer. Customer will not be able to query device afterwards." + TENANT_AUTHORITY_PARAGRAPH)
259 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 285 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
260 @RequestMapping(value = "/customer/device/{deviceId}", method = RequestMethod.DELETE) 286 @RequestMapping(value = "/customer/device/{deviceId}", method = RequestMethod.DELETE)
261 @ResponseBody 287 @ResponseBody
@@ -291,7 +317,7 @@ public class DeviceController extends BaseController { @@ -291,7 +317,7 @@ public class DeviceController extends BaseController {
291 @ApiOperation(value = "Make device publicly available (assignDeviceToPublicCustomer)", 317 @ApiOperation(value = "Make device publicly available (assignDeviceToPublicCustomer)",
292 notes = "Device will be available for non-authorized (not logged-in) users. " + 318 notes = "Device will be available for non-authorized (not logged-in) users. " +
293 "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + 319 "This is useful to create dashboards that you plan to share/embed on a publicly available website. " +
294 - "However, users that are logged-in and belong to different tenant will not be able to access the device.") 320 + "However, users that are logged-in and belong to different tenant will not be able to access the device." + TENANT_AUTHORITY_PARAGRAPH)
295 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 321 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
296 @RequestMapping(value = "/customer/public/device/{deviceId}", method = RequestMethod.POST) 322 @RequestMapping(value = "/customer/public/device/{deviceId}", method = RequestMethod.POST)
297 @ResponseBody 323 @ResponseBody
@@ -318,7 +344,7 @@ public class DeviceController extends BaseController { @@ -318,7 +344,7 @@ public class DeviceController extends BaseController {
318 } 344 }
319 345
320 @ApiOperation(value = "Get Device Credentials (getDeviceCredentialsByDeviceId)", 346 @ApiOperation(value = "Get Device Credentials (getDeviceCredentialsByDeviceId)",
321 - notes = "If during device creation there wasn't specified any credentials, platform generates random 'ACCESS_TOKEN' credentials.") 347 + notes = "If during device creation there wasn't specified any credentials, platform generates random 'ACCESS_TOKEN' credentials." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
322 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 348 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
323 @RequestMapping(value = "/device/{deviceId}/credentials", method = RequestMethod.GET) 349 @RequestMapping(value = "/device/{deviceId}/credentials", method = RequestMethod.GET)
324 @ResponseBody 350 @ResponseBody
@@ -344,7 +370,7 @@ public class DeviceController extends BaseController { @@ -344,7 +370,7 @@ public class DeviceController extends BaseController {
344 @ApiOperation(value = "Update device credentials (updateDeviceCredentials)", notes = "During device creation, platform generates random 'ACCESS_TOKEN' credentials. " + 370 @ApiOperation(value = "Update device credentials (updateDeviceCredentials)", notes = "During device creation, platform generates random 'ACCESS_TOKEN' credentials. " +
345 "Use this method to update the device credentials. First use 'getDeviceCredentialsByDeviceId' to get the credentials id and value. " + 371 "Use this method to update the device credentials. First use 'getDeviceCredentialsByDeviceId' to get the credentials id and value. " +
346 "Then use current method to update the credentials type and value. It is not possible to create multiple device credentials for the same device. " + 372 "Then use current method to update the credentials type and value. It is not possible to create multiple device credentials for the same device. " +
347 - "The structure of device credentials id and value is simple for the 'ACCESS_TOKEN' but is much more complex for the 'MQTT_BASIC' or 'LWM2M_CREDENTIALS'.") 373 + "The structure of device credentials id and value is simple for the 'ACCESS_TOKEN' but is much more complex for the 'MQTT_BASIC' or 'LWM2M_CREDENTIALS'." + TENANT_AUTHORITY_PARAGRAPH)
348 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 374 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
349 @RequestMapping(value = "/device/credentials", method = RequestMethod.POST) 375 @RequestMapping(value = "/device/credentials", method = RequestMethod.POST)
350 @ResponseBody 376 @ResponseBody
@@ -405,7 +431,7 @@ public class DeviceController extends BaseController { @@ -405,7 +431,7 @@ public class DeviceController extends BaseController {
405 431
406 @ApiOperation(value = "Get Tenant Device Infos (getTenantDeviceInfos)", 432 @ApiOperation(value = "Get Tenant Device Infos (getTenantDeviceInfos)",
407 notes = "Returns a page of devices info objects owned by tenant. " + 433 notes = "Returns a page of devices info objects owned by tenant. " +
408 - PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION) 434 + PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
409 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 435 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
410 @RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 436 @RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
411 @ResponseBody 437 @ResponseBody
@@ -443,7 +469,7 @@ public class DeviceController extends BaseController { @@ -443,7 +469,7 @@ public class DeviceController extends BaseController {
443 469
444 @ApiOperation(value = "Get Tenant Device (getTenantDevice)", 470 @ApiOperation(value = "Get Tenant Device (getTenantDevice)",
445 notes = "Requested device must be owned by tenant that the user belongs to. " + 471 notes = "Requested device must be owned by tenant that the user belongs to. " +
446 - "Device name is an unique property of device. So it can be used to identify the device.") 472 + "Device name is an unique property of device. So it can be used to identify the device." + TENANT_AUTHORITY_PARAGRAPH)
447 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 473 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
448 @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET) 474 @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET)
449 @ResponseBody 475 @ResponseBody
@@ -460,7 +486,7 @@ public class DeviceController extends BaseController { @@ -460,7 +486,7 @@ public class DeviceController extends BaseController {
460 486
461 @ApiOperation(value = "Get Customer Devices (getCustomerDevices)", 487 @ApiOperation(value = "Get Customer Devices (getCustomerDevices)",
462 notes = "Returns a page of devices objects assigned to customer. " + 488 notes = "Returns a page of devices objects assigned to customer. " +
463 - PAGE_DATA_PARAMETERS) 489 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
464 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 490 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
465 @RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) 491 @RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET)
466 @ResponseBody 492 @ResponseBody
@@ -497,7 +523,7 @@ public class DeviceController extends BaseController { @@ -497,7 +523,7 @@ public class DeviceController extends BaseController {
497 523
498 @ApiOperation(value = "Get Customer Device Infos (getCustomerDeviceInfos)", 524 @ApiOperation(value = "Get Customer Device Infos (getCustomerDeviceInfos)",
499 notes = "Returns a page of devices info objects assigned to customer. " + 525 notes = "Returns a page of devices info objects assigned to customer. " +
500 - PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION) 526 + PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
501 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 527 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
502 @RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 528 @RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
503 @ResponseBody 529 @ResponseBody
@@ -538,7 +564,7 @@ public class DeviceController extends BaseController { @@ -538,7 +564,7 @@ public class DeviceController extends BaseController {
538 } 564 }
539 565
540 @ApiOperation(value = "Get Devices By Ids (getDevicesByIds)", 566 @ApiOperation(value = "Get Devices By Ids (getDevicesByIds)",
541 - notes = "Requested devices must be owned by tenant or assigned to customer which user is performing the request. ") 567 + notes = "Requested devices must be owned by tenant or assigned to customer which user is performing the request. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
542 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 568 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
543 @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) 569 @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET)
544 @ResponseBody 570 @ResponseBody
@@ -569,7 +595,7 @@ public class DeviceController extends BaseController { @@ -569,7 +595,7 @@ public class DeviceController extends BaseController {
569 @ApiOperation(value = "Find related devices (findByQuery)", 595 @ApiOperation(value = "Find related devices (findByQuery)",
570 notes = "Returns all devices that are related to the specific entity. " + 596 notes = "Returns all devices that are related to the specific entity. " +
571 "The entity id, relation type, device types, depth of the search, and other query parameters defined using complex 'DeviceSearchQuery' object. " + 597 "The entity id, relation type, device types, depth of the search, and other query parameters defined using complex 'DeviceSearchQuery' object. " +
572 - "See 'Model' tab of the Parameters for more info.") 598 + "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
573 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 599 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
574 @RequestMapping(value = "/devices", method = RequestMethod.POST) 600 @RequestMapping(value = "/devices", method = RequestMethod.POST)
575 @ResponseBody 601 @ResponseBody
@@ -597,7 +623,8 @@ public class DeviceController extends BaseController { @@ -597,7 +623,8 @@ public class DeviceController extends BaseController {
597 } 623 }
598 624
599 @ApiOperation(value = "Get Device Types (getDeviceTypes)", 625 @ApiOperation(value = "Get Device Types (getDeviceTypes)",
600 - notes = "Returns a set of unique device profile names based on devices that are either owned by the tenant or assigned to the customer which user is performing the request.") 626 + notes = "Returns a set of unique device profile names based on devices that are either owned by the tenant or assigned to the customer which user is performing the request."
  627 + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
601 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 628 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
602 @RequestMapping(value = "/device/types", method = RequestMethod.GET) 629 @RequestMapping(value = "/device/types", method = RequestMethod.GET)
603 @ResponseBody 630 @ResponseBody
@@ -618,7 +645,7 @@ public class DeviceController extends BaseController { @@ -618,7 +645,7 @@ public class DeviceController extends BaseController {
618 "Once device is claimed, the customer becomes its owner and customer users may access device data as well as control the device. \n" + 645 "Once device is claimed, the customer becomes its owner and customer users may access device data as well as control the device. \n" +
619 "In order to enable claiming devices feature a system parameter security.claim.allowClaimingByDefault should be set to true, " + 646 "In order to enable claiming devices feature a system parameter security.claim.allowClaimingByDefault should be set to true, " +
620 "otherwise a server-side claimingAllowed attribute with the value true is obligatory for provisioned devices. \n" + 647 "otherwise a server-side claimingAllowed attribute with the value true is obligatory for provisioned devices. \n" +
621 - "See official documentation for more details regarding claiming.") 648 + "See official documentation for more details regarding claiming." + CUSTOMER_AUTHORITY_PARAGRAPH)
622 @PreAuthorize("hasAuthority('CUSTOMER_USER')") 649 @PreAuthorize("hasAuthority('CUSTOMER_USER')")
623 @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.POST) 650 @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.POST)
624 @ResponseBody 651 @ResponseBody
@@ -676,7 +703,8 @@ public class DeviceController extends BaseController { @@ -676,7 +703,8 @@ public class DeviceController extends BaseController {
676 } 703 }
677 704
678 @ApiOperation(value = "Reclaim device (reClaimDevice)", 705 @ApiOperation(value = "Reclaim device (reClaimDevice)",
679 - notes = "Reclaiming means the device will be unassigned from the customer and the device will be available for claiming again.") 706 + notes = "Reclaiming means the device will be unassigned from the customer and the device will be available for claiming again."
  707 + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
680 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 708 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
681 @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.DELETE) 709 @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.DELETE)
682 @ResponseStatus(value = HttpStatus.OK) 710 @ResponseStatus(value = HttpStatus.OK)
@@ -730,7 +758,7 @@ public class DeviceController extends BaseController { @@ -730,7 +758,7 @@ public class DeviceController extends BaseController {
730 } 758 }
731 759
732 @ApiOperation(value = "Assign device to tenant (assignDeviceToTenant)", 760 @ApiOperation(value = "Assign device to tenant (assignDeviceToTenant)",
733 - notes = "Creates assignment of the device to tenant. Thereafter tenant will be able to reassign the device to a customer.") 761 + notes = "Creates assignment of the device to tenant. Thereafter tenant will be able to reassign the device to a customer." + TENANT_AUTHORITY_PARAGRAPH)
734 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 762 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
735 @RequestMapping(value = "/tenant/{tenantId}/device/{deviceId}", method = RequestMethod.POST) 763 @RequestMapping(value = "/tenant/{tenantId}/device/{deviceId}", method = RequestMethod.POST)
736 @ResponseBody 764 @ResponseBody
@@ -788,7 +816,7 @@ public class DeviceController extends BaseController { @@ -788,7 +816,7 @@ public class DeviceController extends BaseController {
788 EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + 816 EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
789 "Second, remote edge service will receive a copy of assignment device " + 817 "Second, remote edge service will receive a copy of assignment device " +
790 EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + ". " + 818 EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + ". " +
791 - "Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance.", 819 + "Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH,
792 produces = MediaType.APPLICATION_JSON_VALUE) 820 produces = MediaType.APPLICATION_JSON_VALUE)
793 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 821 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
794 @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST) 822 @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST)
@@ -831,7 +859,7 @@ public class DeviceController extends BaseController { @@ -831,7 +859,7 @@ public class DeviceController extends BaseController {
831 EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + 859 EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
832 "Second, remote edge service will receive an 'unassign' command to remove device " + 860 "Second, remote edge service will receive an 'unassign' command to remove device " +
833 EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + ". " + 861 EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + ". " +
834 - "Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally.", 862 + "Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally." + TENANT_AUTHORITY_PARAGRAPH,
835 produces = MediaType.APPLICATION_JSON_VALUE) 863 produces = MediaType.APPLICATION_JSON_VALUE)
836 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 864 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
837 @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE) 865 @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE)
@@ -871,7 +899,7 @@ public class DeviceController extends BaseController { @@ -871,7 +899,7 @@ public class DeviceController extends BaseController {
871 899
872 @ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)", 900 @ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)",
873 notes = "Returns a page of devices assigned to edge. " + 901 notes = "Returns a page of devices assigned to edge. " +
874 - PAGE_DATA_PARAMETERS) 902 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
875 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 903 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
876 @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) 904 @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET)
877 @ResponseBody 905 @ResponseBody
@@ -928,7 +956,7 @@ public class DeviceController extends BaseController { @@ -928,7 +956,7 @@ public class DeviceController extends BaseController {
928 notes = "The platform gives an ability to load OTA (over-the-air) packages to devices. " + 956 notes = "The platform gives an ability to load OTA (over-the-air) packages to devices. " +
929 "It can be done in two different ways: device scope or device profile scope." + 957 "It can be done in two different ways: device scope or device profile scope." +
930 "In the response you will find the number of devices with specified device profile, but without previously defined device scope OTA package. " + 958 "In the response you will find the number of devices with specified device profile, but without previously defined device scope OTA package. " +
931 - "It can be useful when you want to define number of devices that will be affected with future OTA package") 959 + "It can be useful when you want to define number of devices that will be affected with future OTA package" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
932 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 960 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
933 @RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET) 961 @RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET)
934 @ResponseBody 962 @ResponseBody
@@ -949,7 +977,7 @@ public class DeviceController extends BaseController { @@ -949,7 +977,7 @@ public class DeviceController extends BaseController {
949 } 977 }
950 978
951 @ApiOperation(value = "Import the bulk of devices (processDevicesBulkImport)", 979 @ApiOperation(value = "Import the bulk of devices (processDevicesBulkImport)",
952 - notes = "There's an ability to import the bulk of devices using the only .csv file.") 980 + notes = "There's an ability to import the bulk of devices using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH)
953 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 981 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
954 @PostMapping("/device/bulk_import") 982 @PostMapping("/device/bulk_import")
955 public BulkImportResult<Device> processDevicesBulkImport(@RequestBody BulkImportRequest request) throws Exception { 983 public BulkImportResult<Device> processDevicesBulkImport(@RequestBody BulkImportRequest request) throws Exception {
@@ -49,13 +49,29 @@ import java.util.List; @@ -49,13 +49,29 @@ import java.util.List;
49 import java.util.Objects; 49 import java.util.Objects;
50 import java.util.UUID; 50 import java.util.UUID;
51 51
  52 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_DATA;
  53 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID;
  54 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID_PARAM_DESCRIPTION;
  55 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_INFO_DESCRIPTION;
  56 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES;
  57 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION;
  58 +import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
  59 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  60 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  61 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  62 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  63 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  64 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  65 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  66 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  67 +import static org.thingsboard.server.controller.ControllerConstants.TRANSPORT_TYPE_ALLOWABLE_VALUES;
  68 +
52 @RestController 69 @RestController
53 @TbCoreComponent 70 @TbCoreComponent
54 @RequestMapping("/api") 71 @RequestMapping("/api")
55 @Slf4j 72 @Slf4j
56 public class DeviceProfileController extends BaseController { 73 public class DeviceProfileController extends BaseController {
57 74
58 - private static final String DEVICE_PROFILE_ID = "deviceProfileId";  
59 75
60 @Autowired 76 @Autowired
61 private TimeseriesService timeseriesService; 77 private TimeseriesService timeseriesService;
@@ -81,7 +97,7 @@ public class DeviceProfileController extends BaseController { @@ -81,7 +97,7 @@ public class DeviceProfileController extends BaseController {
81 97
82 @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)", 98 @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)",
83 notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. " 99 notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. "
84 - + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_USER_AUTHORITY_PARAGRAPH, 100 + + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
85 produces = "application/json") 101 produces = "application/json")
86 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 102 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
87 @RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET) 103 @RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET)
@@ -100,7 +116,7 @@ public class DeviceProfileController extends BaseController { @@ -100,7 +116,7 @@ public class DeviceProfileController extends BaseController {
100 116
101 @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)", 117 @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)",
102 notes = "Fetch the Default Device Profile Info object. " + 118 notes = "Fetch the Default Device Profile Info object. " +
103 - DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_USER_AUTHORITY_PARAGRAPH, 119 + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
104 produces = "application/json") 120 produces = "application/json")
105 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 121 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
106 @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET) 122 @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET)
@@ -169,12 +185,13 @@ public class DeviceProfileController extends BaseController { @@ -169,12 +185,13 @@ public class DeviceProfileController extends BaseController {
169 } 185 }
170 } 186 }
171 187
172 - @ApiOperation(value = "Create Or Update Device Profile (saveDevice)", 188 + @ApiOperation(value = "Create Or Update Device Profile (saveDeviceProfile)",
173 notes = "Create or update the Device Profile. When creating device profile, platform generates device profile id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " + 189 notes = "Create or update the Device Profile. When creating device profile, platform generates device profile id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
174 "The newly created device profile id will be present in the response. " + 190 "The newly created device profile id will be present in the response. " +
175 "Specify existing device profile id to update the device profile. " + 191 "Specify existing device profile id to update the device profile. " +
176 - "Referencing non-existing device profile Id will cause 'Not Found' error. " +  
177 - "\n\nDevice profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + TENANT_AUTHORITY_PARAGRAPH, 192 + "Referencing non-existing device profile Id will cause 'Not Found' error. " + NEW_LINE +
  193 + "Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA +
  194 + TENANT_AUTHORITY_PARAGRAPH,
178 produces = "application/json", 195 produces = "application/json",
179 consumes = "application/json") 196 consumes = "application/json")
180 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 197 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@@ -321,7 +338,7 @@ public class DeviceProfileController extends BaseController { @@ -321,7 +338,7 @@ public class DeviceProfileController extends BaseController {
321 338
322 @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)", 339 @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)",
323 notes = "Returns a page of devices profile info objects owned by tenant. " + 340 notes = "Returns a page of devices profile info objects owned by tenant. " +
324 - PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_USER_AUTHORITY_PARAGRAPH, 341 + PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
325 produces = "application/json") 342 produces = "application/json")
326 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 343 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
327 @RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 344 @RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -69,6 +69,22 @@ import java.util.ArrayList; @@ -69,6 +69,22 @@ import java.util.ArrayList;
69 import java.util.List; 69 import java.util.List;
70 import java.util.stream.Collectors; 70 import java.util.stream.Collectors;
71 71
  72 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
  73 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION;
  74 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_INFO_DESCRIPTION;
  75 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_SORT_PROPERTY_ALLOWABLE_VALUES;
  76 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_TEXT_SEARCH_DESCRIPTION;
  77 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_TYPE_DESCRIPTION;
  78 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  79 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  80 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  81 +import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_ID_PARAM_DESCRIPTION;
  82 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  83 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  84 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  85 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  86 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  87 +
72 @RestController 88 @RestController
73 @TbCoreComponent 89 @TbCoreComponent
74 @Slf4j 90 @Slf4j
@@ -91,7 +107,7 @@ public class EdgeController extends BaseController { @@ -91,7 +107,7 @@ public class EdgeController extends BaseController {
91 } 107 }
92 108
93 @ApiOperation(value = "Get Edge (getEdgeById)", 109 @ApiOperation(value = "Get Edge (getEdgeById)",
94 - notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK, 110 + notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
95 produces = MediaType.APPLICATION_JSON_VALUE) 111 produces = MediaType.APPLICATION_JSON_VALUE)
96 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 112 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
97 @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET) 113 @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET)
@@ -112,7 +128,7 @@ public class EdgeController extends BaseController { @@ -112,7 +128,7 @@ public class EdgeController extends BaseController {
112 } 128 }
113 129
114 @ApiOperation(value = "Get Edge Info (getEdgeInfoById)", 130 @ApiOperation(value = "Get Edge Info (getEdgeInfoById)",
115 - notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK, 131 + notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
116 produces = MediaType.APPLICATION_JSON_VALUE) 132 produces = MediaType.APPLICATION_JSON_VALUE)
117 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 133 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
118 @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET) 134 @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET)
@@ -137,7 +153,8 @@ public class EdgeController extends BaseController { @@ -137,7 +153,8 @@ public class EdgeController extends BaseController {
137 "The newly created edge id will be present in the response. " + 153 "The newly created edge id will be present in the response. " +
138 "Specify existing Edge id to update the edge. " + 154 "Specify existing Edge id to update the edge. " +
139 "Referencing non-existing Edge Id will cause 'Not Found' error." + 155 "Referencing non-existing Edge Id will cause 'Not Found' error." +
140 - "\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes.", 156 + "\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes."
  157 + + TENANT_AUTHORITY_PARAGRAPH,
141 produces = MediaType.APPLICATION_JSON_VALUE) 158 produces = MediaType.APPLICATION_JSON_VALUE)
142 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 159 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
143 @RequestMapping(value = "/edge", method = RequestMethod.POST) 160 @RequestMapping(value = "/edge", method = RequestMethod.POST)
@@ -187,7 +204,7 @@ public class EdgeController extends BaseController { @@ -187,7 +204,7 @@ public class EdgeController extends BaseController {
187 } 204 }
188 205
189 @ApiOperation(value = "Delete edge (deleteEdge)", 206 @ApiOperation(value = "Delete edge (deleteEdge)",
190 - notes = "Deletes the edge. Referencing non-existing edge Id will cause an error.") 207 + notes = "Deletes the edge. Referencing non-existing edge Id will cause an error."+ TENANT_AUTHORITY_PARAGRAPH)
191 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 208 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
192 @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.DELETE) 209 @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.DELETE)
193 @ResponseStatus(value = HttpStatus.OK) 210 @ResponseStatus(value = HttpStatus.OK)
@@ -219,7 +236,7 @@ public class EdgeController extends BaseController { @@ -219,7 +236,7 @@ public class EdgeController extends BaseController {
219 236
220 @ApiOperation(value = "Get Tenant Edges (getEdges)", 237 @ApiOperation(value = "Get Tenant Edges (getEdges)",
221 notes = "Returns a page of edges owned by tenant. " + 238 notes = "Returns a page of edges owned by tenant. " +
222 - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) 239 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
223 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 240 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
224 @RequestMapping(value = "/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) 241 @RequestMapping(value = "/edges", params = {"pageSize", "page"}, method = RequestMethod.GET)
225 @ResponseBody 242 @ResponseBody
@@ -243,7 +260,7 @@ public class EdgeController extends BaseController { @@ -243,7 +260,7 @@ public class EdgeController extends BaseController {
243 } 260 }
244 261
245 @ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)", 262 @ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)",
246 - notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards.", 263 + notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH,
247 produces = MediaType.APPLICATION_JSON_VALUE) 264 produces = MediaType.APPLICATION_JSON_VALUE)
248 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 265 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
249 @RequestMapping(value = "/customer/{customerId}/edge/{edgeId}", method = RequestMethod.POST) 266 @RequestMapping(value = "/customer/{customerId}/edge/{edgeId}", method = RequestMethod.POST)
@@ -283,7 +300,7 @@ public class EdgeController extends BaseController { @@ -283,7 +300,7 @@ public class EdgeController extends BaseController {
283 } 300 }
284 301
285 @ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)", 302 @ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)",
286 - notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards.", 303 + notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH,
287 produces = MediaType.APPLICATION_JSON_VALUE) 304 produces = MediaType.APPLICATION_JSON_VALUE)
288 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 305 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
289 @RequestMapping(value = "/customer/edge/{edgeId}", method = RequestMethod.DELETE) 306 @RequestMapping(value = "/customer/edge/{edgeId}", method = RequestMethod.DELETE)
@@ -323,7 +340,7 @@ public class EdgeController extends BaseController { @@ -323,7 +340,7 @@ public class EdgeController extends BaseController {
323 @ApiOperation(value = "Make edge publicly available (assignEdgeToPublicCustomer)", 340 @ApiOperation(value = "Make edge publicly available (assignEdgeToPublicCustomer)",
324 notes = "Edge will be available for non-authorized (not logged-in) users. " + 341 notes = "Edge will be available for non-authorized (not logged-in) users. " +
325 "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + 342 "This is useful to create dashboards that you plan to share/embed on a publicly available website. " +
326 - "However, users that are logged-in and belong to different tenant will not be able to access the edge.", 343 + "However, users that are logged-in and belong to different tenant will not be able to access the edge." + TENANT_AUTHORITY_PARAGRAPH,
327 produces = MediaType.APPLICATION_JSON_VALUE) 344 produces = MediaType.APPLICATION_JSON_VALUE)
328 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 345 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
329 @RequestMapping(value = "/customer/public/edge/{edgeId}", method = RequestMethod.POST) 346 @RequestMapping(value = "/customer/public/edge/{edgeId}", method = RequestMethod.POST)
@@ -355,7 +372,7 @@ public class EdgeController extends BaseController { @@ -355,7 +372,7 @@ public class EdgeController extends BaseController {
355 372
356 @ApiOperation(value = "Get Tenant Edges (getTenantEdges)", 373 @ApiOperation(value = "Get Tenant Edges (getTenantEdges)",
357 notes = "Returns a page of edges owned by tenant. " + 374 notes = "Returns a page of edges owned by tenant. " +
358 - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) 375 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
359 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 376 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
360 @RequestMapping(value = "/tenant/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) 377 @RequestMapping(value = "/tenant/edges", params = {"pageSize", "page"}, method = RequestMethod.GET)
361 @ResponseBody 378 @ResponseBody
@@ -387,7 +404,7 @@ public class EdgeController extends BaseController { @@ -387,7 +404,7 @@ public class EdgeController extends BaseController {
387 404
388 @ApiOperation(value = "Get Tenant Edge Infos (getTenantEdgeInfos)", 405 @ApiOperation(value = "Get Tenant Edge Infos (getTenantEdgeInfos)",
389 notes = "Returns a page of edges info objects owned by tenant. " + 406 notes = "Returns a page of edges info objects owned by tenant. " +
390 - PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION, 407 + PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH,
391 produces = MediaType.APPLICATION_JSON_VALUE) 408 produces = MediaType.APPLICATION_JSON_VALUE)
392 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 409 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
393 @RequestMapping(value = "/tenant/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 410 @RequestMapping(value = "/tenant/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@@ -420,7 +437,7 @@ public class EdgeController extends BaseController { @@ -420,7 +437,7 @@ public class EdgeController extends BaseController {
420 437
421 @ApiOperation(value = "Get Tenant Edge (getTenantEdge)", 438 @ApiOperation(value = "Get Tenant Edge (getTenantEdge)",
422 notes = "Requested edge must be owned by tenant or customer that the user belongs to. " + 439 notes = "Requested edge must be owned by tenant or customer that the user belongs to. " +
423 - "Edge name is an unique property of edge. So it can be used to identify the edge.", 440 + "Edge name is an unique property of edge. So it can be used to identify the edge." + TENANT_AUTHORITY_PARAGRAPH,
424 produces = MediaType.APPLICATION_JSON_VALUE) 441 produces = MediaType.APPLICATION_JSON_VALUE)
425 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 442 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
426 @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET) 443 @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET)
@@ -437,7 +454,7 @@ public class EdgeController extends BaseController { @@ -437,7 +454,7 @@ public class EdgeController extends BaseController {
437 454
438 @ApiOperation(value = "Set root rule chain for provided edge (setRootRuleChain)", 455 @ApiOperation(value = "Set root rule chain for provided edge (setRootRuleChain)",
439 notes = "Change root rule chain of the edge to the new provided rule chain. \n" + 456 notes = "Change root rule chain of the edge to the new provided rule chain. \n" +
440 - "This operation will send a notification to update root rule chain on remote edge service.", 457 + "This operation will send a notification to update root rule chain on remote edge service." + TENANT_AUTHORITY_PARAGRAPH,
441 produces = MediaType.APPLICATION_JSON_VALUE) 458 produces = MediaType.APPLICATION_JSON_VALUE)
442 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 459 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
443 @RequestMapping(value = "/edge/{edgeId}/{ruleChainId}/root", method = RequestMethod.POST) 460 @RequestMapping(value = "/edge/{edgeId}/{ruleChainId}/root", method = RequestMethod.POST)
@@ -475,7 +492,7 @@ public class EdgeController extends BaseController { @@ -475,7 +492,7 @@ public class EdgeController extends BaseController {
475 492
476 @ApiOperation(value = "Get Customer Edges (getCustomerEdges)", 493 @ApiOperation(value = "Get Customer Edges (getCustomerEdges)",
477 notes = "Returns a page of edges objects assigned to customer. " + 494 notes = "Returns a page of edges objects assigned to customer. " +
478 - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) 495 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
479 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 496 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
480 @RequestMapping(value = "/customer/{customerId}/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) 497 @RequestMapping(value = "/customer/{customerId}/edges", params = {"pageSize", "page"}, method = RequestMethod.GET)
481 @ResponseBody 498 @ResponseBody
@@ -520,7 +537,7 @@ public class EdgeController extends BaseController { @@ -520,7 +537,7 @@ public class EdgeController extends BaseController {
520 537
521 @ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)", 538 @ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)",
522 notes = "Returns a page of edges info objects assigned to customer. " + 539 notes = "Returns a page of edges info objects assigned to customer. " +
523 - PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE) 540 + PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE)
524 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 541 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
525 @RequestMapping(value = "/customer/{customerId}/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 542 @RequestMapping(value = "/customer/{customerId}/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
526 @ResponseBody 543 @ResponseBody
@@ -564,7 +581,7 @@ public class EdgeController extends BaseController { @@ -564,7 +581,7 @@ public class EdgeController extends BaseController {
564 } 581 }
565 582
566 @ApiOperation(value = "Get Edges By Ids (getEdgesByIds)", 583 @ApiOperation(value = "Get Edges By Ids (getEdgesByIds)",
567 - notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request.", 584 + notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
568 produces = MediaType.APPLICATION_JSON_VALUE) 585 produces = MediaType.APPLICATION_JSON_VALUE)
569 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 586 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
570 @RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET) 587 @RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET)
@@ -602,7 +619,7 @@ public class EdgeController extends BaseController { @@ -602,7 +619,7 @@ public class EdgeController extends BaseController {
602 @ApiOperation(value = "Find related edges (findByQuery)", 619 @ApiOperation(value = "Find related edges (findByQuery)",
603 notes = "Returns all edges that are related to the specific entity. " + 620 notes = "Returns all edges that are related to the specific entity. " +
604 "The entity id, relation type, edge types, depth of the search, and other query parameters defined using complex 'EdgeSearchQuery' object. " + 621 "The entity id, relation type, edge types, depth of the search, and other query parameters defined using complex 'EdgeSearchQuery' object. " +
605 - "See 'Model' tab of the Parameters for more info.", 622 + "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
606 produces = MediaType.APPLICATION_JSON_VALUE) 623 produces = MediaType.APPLICATION_JSON_VALUE)
607 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 624 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
608 @RequestMapping(value = "/edges", method = RequestMethod.POST) 625 @RequestMapping(value = "/edges", method = RequestMethod.POST)
@@ -636,7 +653,8 @@ public class EdgeController extends BaseController { @@ -636,7 +653,8 @@ public class EdgeController extends BaseController {
636 } 653 }
637 654
638 @ApiOperation(value = "Get Edge Types (getEdgeTypes)", 655 @ApiOperation(value = "Get Edge Types (getEdgeTypes)",
639 - notes = "Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request.", 656 + notes = "Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request."
  657 + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
640 produces = MediaType.APPLICATION_JSON_VALUE) 658 produces = MediaType.APPLICATION_JSON_VALUE)
641 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 659 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
642 @RequestMapping(value = "/edge/types", method = RequestMethod.GET) 660 @RequestMapping(value = "/edge/types", method = RequestMethod.GET)
@@ -654,7 +672,7 @@ public class EdgeController extends BaseController { @@ -654,7 +672,7 @@ public class EdgeController extends BaseController {
654 672
655 @ApiOperation(value = "Sync edge (syncEdge)", 673 @ApiOperation(value = "Sync edge (syncEdge)",
656 notes = "Starts synchronization process between edge and cloud. \n" + 674 notes = "Starts synchronization process between edge and cloud. \n" +
657 - "All entities that are assigned to particular edge are going to be send to remote edge service.") 675 + "All entities that are assigned to particular edge are going to be send to remote edge service." + TENANT_AUTHORITY_PARAGRAPH)
658 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 676 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
659 @RequestMapping(value = "/edge/sync/{edgeId}", method = RequestMethod.POST) 677 @RequestMapping(value = "/edge/sync/{edgeId}", method = RequestMethod.POST)
660 public void syncEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) 678 public void syncEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@@ -676,7 +694,7 @@ public class EdgeController extends BaseController { @@ -676,7 +694,7 @@ public class EdgeController extends BaseController {
676 } 694 }
677 695
678 @ApiOperation(value = "Find missing rule chains (findMissingToRelatedRuleChains)", 696 @ApiOperation(value = "Find missing rule chains (findMissingToRelatedRuleChains)",
679 - notes = "Returns list of rule chains ids that are not assigned to particular edge, but these rule chains are present in the already assigned rule chains to edge.") 697 + notes = "Returns list of rule chains ids that are not assigned to particular edge, but these rule chains are present in the already assigned rule chains to edge." + TENANT_AUTHORITY_PARAGRAPH)
680 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 698 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
681 @RequestMapping(value = "/edge/missingToRelatedRuleChains/{edgeId}", method = RequestMethod.GET) 699 @RequestMapping(value = "/edge/missingToRelatedRuleChains/{edgeId}", method = RequestMethod.GET)
682 @ResponseBody 700 @ResponseBody
@@ -694,7 +712,7 @@ public class EdgeController extends BaseController { @@ -694,7 +712,7 @@ public class EdgeController extends BaseController {
694 } 712 }
695 713
696 @ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)", 714 @ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)",
697 - notes = "There's an ability to import the bulk of edges using the only .csv file.", 715 + notes = "There's an ability to import the bulk of edges using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH,
698 produces = MediaType.APPLICATION_JSON_VALUE) 716 produces = MediaType.APPLICATION_JSON_VALUE)
699 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 717 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
700 @PostMapping("/edge/bulk_import") 718 @PostMapping("/edge/bulk_import")
@@ -37,6 +37,15 @@ import org.thingsboard.server.dao.edge.EdgeEventService; @@ -37,6 +37,15 @@ import org.thingsboard.server.dao.edge.EdgeEventService;
37 import org.thingsboard.server.queue.util.TbCoreComponent; 37 import org.thingsboard.server.queue.util.TbCoreComponent;
38 import org.thingsboard.server.service.security.permission.Operation; 38 import org.thingsboard.server.service.security.permission.Operation;
39 39
  40 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION;
  41 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_SORT_PROPERTY_ALLOWABLE_VALUES;
  42 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  43 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  44 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  45 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  46 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  47 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  48 +
40 @Slf4j 49 @Slf4j
41 @RestController 50 @RestController
42 @TbCoreComponent 51 @TbCoreComponent
@@ -39,643 +39,15 @@ import org.thingsboard.server.common.data.query.EntityDataQuery; @@ -39,643 +39,15 @@ import org.thingsboard.server.common.data.query.EntityDataQuery;
39 import org.thingsboard.server.queue.util.TbCoreComponent; 39 import org.thingsboard.server.queue.util.TbCoreComponent;
40 import org.thingsboard.server.service.query.EntityQueryService; 40 import org.thingsboard.server.service.query.EntityQueryService;
41 41
  42 +import static org.thingsboard.server.controller.ControllerConstants.ALARM_DATA_QUERY_DESCRIPTION;
  43 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_COUNT_QUERY_DESCRIPTION;
  44 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_DATA_QUERY_DESCRIPTION;
  45 +
42 @RestController 46 @RestController
43 @TbCoreComponent 47 @TbCoreComponent
44 @RequestMapping("/api") 48 @RequestMapping("/api")
45 public class EntityQueryController extends BaseController { 49 public class EntityQueryController extends BaseController {
46 50
47 - private static final String SINGLE_ENTITY = "\n\n## Single Entity\n\n" +  
48 - "Allows to filter only one entity based on the id. For example, this entity filter selects certain device:\n\n"+  
49 - MARKDOWN_CODE_BLOCK_START +  
50 - "{\n" +  
51 - " \"type\": \"singleEntity\",\n" +  
52 - " \"singleEntity\": {\n" +  
53 - " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +  
54 - " \"entityType\": \"DEVICE\"\n" +  
55 - " }\n" +  
56 - "}"+  
57 - MARKDOWN_CODE_BLOCK_END +  
58 - "";  
59 -  
60 - private static final String ENTITY_LIST = "\n\n## Entity List Filter\n\n" +  
61 - "Allows to filter entities of the same type using their ids. For example, this entity filter selects two devices:\n\n"+  
62 - MARKDOWN_CODE_BLOCK_START +  
63 - "{\n" +  
64 - " \"type\": \"entityList\",\n" +  
65 - " \"entityType\": \"DEVICE\",\n" +  
66 - " \"entityList\": [\n" +  
67 - " \"e6501f30-2a7a-11ec-94eb-213c95f54092\",\n" +  
68 - " \"e6657bf0-2a7a-11ec-94eb-213c95f54092\"\n" +  
69 - " ]\n" +  
70 - "}"+  
71 - MARKDOWN_CODE_BLOCK_END +  
72 - "";  
73 -  
74 - private static final String ENTITY_NAME = "\n\n## Entity Name Filter\n\n" +  
75 - "Allows to filter entities of the same type using the **'starts with'** expression over entity name. " +  
76 - "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n"+  
77 - MARKDOWN_CODE_BLOCK_START +  
78 - "{\n" +  
79 - " \"type\": \"entityName\",\n" +  
80 - " \"entityType\": \"DEVICE\",\n" +  
81 - " \"entityNameFilter\": \"Air Quality\"\n" +  
82 - "}"+  
83 - MARKDOWN_CODE_BLOCK_END +  
84 - "";  
85 -  
86 - private static final String ENTITY_TYPE = "\n\n## Entity Type Filter\n\n" +  
87 - "Allows to filter entities based on their type (CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, etc)" +  
88 - "For example, this entity filter selects all tenant customers:\n\n"+  
89 - MARKDOWN_CODE_BLOCK_START +  
90 - "{\n" +  
91 - " \"type\": \"entityType\",\n" +  
92 - " \"entityType\": \"CUSTOMER\"\n" +  
93 - "}"+  
94 - MARKDOWN_CODE_BLOCK_END +  
95 - "";  
96 -  
97 - private static final String ASSET_TYPE = "\n\n## Asset Type Filter\n\n" +  
98 - "Allows to filter assets based on their type and the **'starts with'** expression over their name. " +  
99 - "For example, this entity filter selects all 'charging station' assets which name starts with 'Tesla':\n\n"+  
100 - MARKDOWN_CODE_BLOCK_START +  
101 - "{\n" +  
102 - " \"type\": \"assetType\",\n" +  
103 - " \"assetType\": \"charging station\",\n" +  
104 - " \"assetNameFilter\": \"Tesla\"\n" +  
105 - "}"+  
106 - MARKDOWN_CODE_BLOCK_END +  
107 - "";  
108 -  
109 - private static final String DEVICE_TYPE = "\n\n## Device Type Filter\n\n" +  
110 - "Allows to filter devices based on their type and the **'starts with'** expression over their name. " +  
111 - "For example, this entity filter selects all 'Temperature Sensor' devices which name starts with 'ABC':\n\n"+  
112 - MARKDOWN_CODE_BLOCK_START +  
113 - "{\n" +  
114 - " \"type\": \"deviceType\",\n" +  
115 - " \"deviceType\": \"Temperature Sensor\",\n" +  
116 - " \"deviceNameFilter\": \"ABC\"\n" +  
117 - "}"+  
118 - MARKDOWN_CODE_BLOCK_END +  
119 - "";  
120 -  
121 - private static final String EDGE_TYPE = "\n\n## Edge Type Filter\n\n" +  
122 - "Allows to filter edge instances based on their type and the **'starts with'** expression over their name. " +  
123 - "For example, this entity filter selects all 'Factory' edge instances which name starts with 'Nevada':\n\n"+  
124 - MARKDOWN_CODE_BLOCK_START +  
125 - "{\n" +  
126 - " \"type\": \"edgeType\",\n" +  
127 - " \"edgeType\": \"Factory\",\n" +  
128 - " \"edgeNameFilter\": \"Nevada\"\n" +  
129 - "}"+  
130 - MARKDOWN_CODE_BLOCK_END +  
131 - "";  
132 -  
133 - private static final String ENTITY_VIEW_TYPE = "\n\n## Entity View Filter\n\n" +  
134 - "Allows to filter entity views based on their type and the **'starts with'** expression over their name. " +  
135 - "For example, this entity filter selects all 'Concrete Mixer' entity views which name starts with 'CAT':\n\n"+  
136 - MARKDOWN_CODE_BLOCK_START +  
137 - "{\n" +  
138 - " \"type\": \"entityViewType\",\n" +  
139 - " \"entityViewType\": \"Concrete Mixer\",\n" +  
140 - " \"entityViewNameFilter\": \"CAT\"\n" +  
141 - "}"+  
142 - MARKDOWN_CODE_BLOCK_END +  
143 - "";  
144 -  
145 - private static final String API_USAGE = "\n\n## Api Usage Filter\n\n" +  
146 - "Allows to query for Api Usage based on optional customer id. If the customer id is not set, returns current tenant API usage." +  
147 - "For example, this entity filter selects the 'Api Usage' entity for customer with id 'e6501f30-2a7a-11ec-94eb-213c95f54092':\n\n"+  
148 - MARKDOWN_CODE_BLOCK_START +  
149 - "{\n" +  
150 - " \"type\": \"apiUsageState\",\n" +  
151 - " \"customerId\": {\n" +  
152 - " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +  
153 - " \"entityType\": \"CUSTOMER\"\n" +  
154 - " }\n" +  
155 - "}"+  
156 - MARKDOWN_CODE_BLOCK_END +  
157 - "";  
158 -  
159 - private static final String MAX_LEVEL_DESCRIPTION = "Possible direction values are 'TO' and 'FROM'. The 'maxLevel' defines how many relation levels should the query search 'recursively'. ";  
160 - private static final String FETCH_LAST_LEVEL_ONLY_DESCRIPTION = "Assuming the 'maxLevel' is > 1, the 'fetchLastLevelOnly' defines either to return all related entities or only entities that are on the last level of relations. ";  
161 -  
162 - private static final String RELATIONS_QUERY_FILTER = "\n\n## Relations Query Filter\n\n" +  
163 - "Allows to filter entities that are related to the provided root entity. " +  
164 - MAX_LEVEL_DESCRIPTION +  
165 - FETCH_LAST_LEVEL_ONLY_DESCRIPTION +  
166 - "The 'filter' object allows you to define the relation type and set of acceptable entity types to search for. " +  
167 - "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only those who match the 'filters'.\n\n" +  
168 - "For example, this entity filter selects all devices and assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092':\n\n"+  
169 - MARKDOWN_CODE_BLOCK_START +  
170 - "{\n" +  
171 - " \"type\": \"relationsQuery\",\n" +  
172 - " \"rootEntity\": {\n" +  
173 - " \"entityType\": \"ASSET\",\n" +  
174 - " \"id\": \"e51de0c0-2a7a-11ec-94eb-213c95f54092\"\n" +  
175 - " },\n" +  
176 - " \"direction\": \"FROM\",\n" +  
177 - " \"maxLevel\": 1,\n" +  
178 - " \"fetchLastLevelOnly\": false,\n" +  
179 - " \"filters\": [\n" +  
180 - " {\n" +  
181 - " \"relationType\": \"Contains\",\n" +  
182 - " \"entityTypes\": [\n" +  
183 - " \"DEVICE\",\n" +  
184 - " \"ASSET\"\n" +  
185 - " ]\n" +  
186 - " }\n" +  
187 - " ]\n" +  
188 - "}"+  
189 - MARKDOWN_CODE_BLOCK_END +  
190 - "";  
191 -  
192 -  
193 - private static final String ASSET_QUERY_FILTER = "\n\n## Asset Search Query\n\n" +  
194 - "Allows to filter assets that are related to the provided root entity. Filters related assets based on the relation type and set of asset types. " +  
195 - MAX_LEVEL_DESCRIPTION +  
196 - FETCH_LAST_LEVEL_ONLY_DESCRIPTION +  
197 - "The 'relationType' defines the type of the relation to search for. " +  
198 - "The 'assetTypes' defines the type of the asset to search for. " +  
199 - "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only assets that match 'relationType' and 'assetTypes' conditions.\n\n" +  
200 - "For example, this entity filter selects 'charging station' assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+  
201 - MARKDOWN_CODE_BLOCK_START +  
202 - "{\n" +  
203 - " \"type\": \"assetSearchQuery\",\n" +  
204 - " \"rootEntity\": {\n" +  
205 - " \"entityType\": \"ASSET\",\n" +  
206 - " \"id\": \"e51de0c0-2a7a-11ec-94eb-213c95f54092\"\n" +  
207 - " },\n" +  
208 - " \"direction\": \"FROM\",\n" +  
209 - " \"maxLevel\": 1,\n" +  
210 - " \"fetchLastLevelOnly\": false,\n" +  
211 - " \"relationType\": \"Contains\",\n" +  
212 - " \"assetTypes\": [\n" +  
213 - " \"charging station\"\n" +  
214 - " ]\n" +  
215 - "}"+  
216 - MARKDOWN_CODE_BLOCK_END +  
217 - "";  
218 -  
219 - private static final String DEVICE_QUERY_FILTER = "\n\n## Device Search Query\n\n" +  
220 - "Allows to filter devices that are related to the provided root entity. Filters related devices based on the relation type and set of device types. " +  
221 - MAX_LEVEL_DESCRIPTION +  
222 - FETCH_LAST_LEVEL_ONLY_DESCRIPTION +  
223 - "The 'relationType' defines the type of the relation to search for. " +  
224 - "The 'deviceTypes' defines the type of the device to search for. " +  
225 - "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +  
226 - "For example, this entity filter selects 'Charging port' and 'Air Quality Sensor' devices which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+  
227 - MARKDOWN_CODE_BLOCK_START +  
228 - "{\n" +  
229 - " \"type\": \"deviceSearchQuery\",\n" +  
230 - " \"rootEntity\": {\n" +  
231 - " \"entityType\": \"ASSET\",\n" +  
232 - " \"id\": \"e52b0020-2a7a-11ec-94eb-213c95f54092\"\n" +  
233 - " },\n" +  
234 - " \"direction\": \"FROM\",\n" +  
235 - " \"maxLevel\": 2,\n" +  
236 - " \"fetchLastLevelOnly\": true,\n" +  
237 - " \"relationType\": \"Contains\",\n" +  
238 - " \"deviceTypes\": [\n" +  
239 - " \"Air Quality Sensor\",\n" +  
240 - " \"Charging port\"\n" +  
241 - " ]\n" +  
242 - "}"+  
243 - MARKDOWN_CODE_BLOCK_END +  
244 - "";  
245 -  
246 - private static final String EV_QUERY_FILTER = "\n\n## Entity View Query\n\n" +  
247 - "Allows to filter entity views that are related to the provided root entity. Filters related entity views based on the relation type and set of entity view types. " +  
248 - MAX_LEVEL_DESCRIPTION +  
249 - FETCH_LAST_LEVEL_ONLY_DESCRIPTION +  
250 - "The 'relationType' defines the type of the relation to search for. " +  
251 - "The 'entityViewTypes' defines the type of the entity view to search for. " +  
252 - "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +  
253 - "For example, this entity filter selects 'Concrete mixer' entity views which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+  
254 - MARKDOWN_CODE_BLOCK_START +  
255 - "{\n" +  
256 - " \"type\": \"entityViewSearchQuery\",\n" +  
257 - " \"rootEntity\": {\n" +  
258 - " \"entityType\": \"ASSET\",\n" +  
259 - " \"id\": \"e52b0020-2a7a-11ec-94eb-213c95f54092\"\n" +  
260 - " },\n" +  
261 - " \"direction\": \"FROM\",\n" +  
262 - " \"maxLevel\": 1,\n" +  
263 - " \"fetchLastLevelOnly\": false,\n" +  
264 - " \"relationType\": \"Contains\",\n" +  
265 - " \"entityViewTypes\": [\n" +  
266 - " \"Concrete mixer\"\n" +  
267 - " ]\n" +  
268 - "}"+  
269 - MARKDOWN_CODE_BLOCK_END +  
270 - "";  
271 -  
272 - private static final String EDGE_QUERY_FILTER = "\n\n## Edge Search Query\n\n" +  
273 - "Allows to filter edge instances that are related to the provided root entity. Filters related edge instances based on the relation type and set of edge types. " +  
274 - MAX_LEVEL_DESCRIPTION +  
275 - FETCH_LAST_LEVEL_ONLY_DESCRIPTION +  
276 - "The 'relationType' defines the type of the relation to search for. " +  
277 - "The 'deviceTypes' defines the type of the device to search for. " +  
278 - "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +  
279 - "For example, this entity filter selects 'Factory' edge instances which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+  
280 - MARKDOWN_CODE_BLOCK_START +  
281 - "{\n" +  
282 - " \"type\": \"deviceSearchQuery\",\n" +  
283 - " \"rootEntity\": {\n" +  
284 - " \"entityType\": \"ASSET\",\n" +  
285 - " \"id\": \"e52b0020-2a7a-11ec-94eb-213c95f54092\"\n" +  
286 - " },\n" +  
287 - " \"direction\": \"FROM\",\n" +  
288 - " \"maxLevel\": 2,\n" +  
289 - " \"fetchLastLevelOnly\": true,\n" +  
290 - " \"relationType\": \"Contains\",\n" +  
291 - " \"edgeTypes\": [\n" +  
292 - " \"Factory\"\n" +  
293 - " ]\n" +  
294 - "}"+  
295 - MARKDOWN_CODE_BLOCK_END +  
296 - "";  
297 -  
298 - private static final String EMPTY = "\n\n## Entity Type Filter\n\n" +  
299 - "Allows to filter multiple entities of the same type using the **'starts with'** expression over entity name. " +  
300 - "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n"+  
301 - MARKDOWN_CODE_BLOCK_START +  
302 - ""+  
303 - MARKDOWN_CODE_BLOCK_END +  
304 - "";  
305 -  
306 - private static final String ENTITY_FILTERS =  
307 - "\n\n # Entity Filters" +  
308 - "\nEntity Filter body depends on the 'type' parameter. Let's review available entity filter types. In fact, they do correspond to available dashboard aliases." +  
309 - SINGLE_ENTITY + ENTITY_LIST + ENTITY_NAME + ENTITY_TYPE + ASSET_TYPE + DEVICE_TYPE + EDGE_TYPE + ENTITY_VIEW_TYPE + API_USAGE + RELATIONS_QUERY_FILTER  
310 - + ASSET_QUERY_FILTER + DEVICE_QUERY_FILTER + EV_QUERY_FILTER + EDGE_QUERY_FILTER;  
311 -  
312 - private static final String FILTER_KEY = "\n\n## Filter Key\n\n" +  
313 - "Filter Key defines either entity field, attribute or telemetry. It is a JSON object that consists the key name and type. " +  
314 - "The following filter key types are supported: \n\n"+  
315 - " * 'CLIENT_ATTRIBUTE' - used for client attributes; \n" +  
316 - " * 'SHARED_ATTRIBUTE' - used for shared attributes; \n" +  
317 - " * 'SERVER_ATTRIBUTE' - used for server attributes; \n" +  
318 - " * 'ATTRIBUTE' - used for any of the above; \n" +  
319 - " * 'TIME_SERIES' - used for time-series values; \n" +  
320 - " * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type; \n" +  
321 - " * 'ALARM_FIELD' - similar to entity field, but is used in alarm queries only; \n" +  
322 - "\n\n Let's review the example:\n\n" +  
323 - MARKDOWN_CODE_BLOCK_START +  
324 - "{\n" +  
325 - " \"type\": \"TIME_SERIES\",\n" +  
326 - " \"key\": \"temperature\"\n" +  
327 - "}" +  
328 - MARKDOWN_CODE_BLOCK_END +  
329 - "";  
330 -  
331 - private static final String FILTER_VALUE_TYPE = "\n\n## Value Type and Operations\n\n" +  
332 - "Provides a hint about the data type of the entity field that is defined in the filter key. " +  
333 - "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." +  
334 - "The following filter value types and corresponding predicate operations are supported: \n\n"+  
335 - " * 'STRING' - used to filter any 'String' or 'JSON' values. Operations: EQUAL, NOT_EQUAL, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS; \n" +  
336 - " * 'NUMERIC' - used for 'Long' and 'Double' values. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n" +  
337 - " * 'BOOLEAN' - used for boolean values; Operations: EQUAL, NOT_EQUAL \n" +  
338 - " * 'DATE_TIME' - similar to numeric, transforms value to milliseconds since epoch. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n";  
339 -  
340 - private static final String FILTER_PREDICATE = "\n\n## Filter Predicate\n\n" +  
341 - "Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +  
342 - "Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." +  
343 - "\n\nSimple predicate example to check 'value < 100': \n\n"+  
344 - MARKDOWN_CODE_BLOCK_START +  
345 - "{\n" +  
346 - " \"operation\": \"LESS\",\n" +  
347 - " \"value\": {\n" +  
348 - " \"defaultValue\": 100,\n" +  
349 - " \"dynamicValue\": null\n" +  
350 - " },\n" +  
351 - " \"type\": \"NUMERIC\"\n" +  
352 - "}" +  
353 - MARKDOWN_CODE_BLOCK_END +  
354 - "\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n"+  
355 - MARKDOWN_CODE_BLOCK_START +  
356 - "{\n" +  
357 - " \"type\": \"COMPLEX\",\n" +  
358 - " \"operation\": \"OR\",\n" +  
359 - " \"predicates\": [\n" +  
360 - " {\n" +  
361 - " \"operation\": \"LESS\",\n" +  
362 - " \"value\": {\n" +  
363 - " \"defaultValue\": 10,\n" +  
364 - " \"dynamicValue\": null\n" +  
365 - " },\n" +  
366 - " \"type\": \"NUMERIC\"\n" +  
367 - " },\n" +  
368 - " {\n" +  
369 - " \"operation\": \"GREATER\",\n" +  
370 - " \"value\": {\n" +  
371 - " \"defaultValue\": 20,\n" +  
372 - " \"dynamicValue\": null\n" +  
373 - " },\n" +  
374 - " \"type\": \"NUMERIC\"\n" +  
375 - " }\n" +  
376 - " ]\n" +  
377 - "}" +  
378 - MARKDOWN_CODE_BLOCK_END +  
379 - "\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n"+  
380 - MARKDOWN_CODE_BLOCK_START +  
381 - "{\n" +  
382 - " \"type\": \"COMPLEX\",\n" +  
383 - " \"operation\": \"OR\",\n" +  
384 - " \"predicates\": [\n" +  
385 - " {\n" +  
386 - " \"operation\": \"LESS\",\n" +  
387 - " \"value\": {\n" +  
388 - " \"defaultValue\": 10,\n" +  
389 - " \"dynamicValue\": null\n" +  
390 - " },\n" +  
391 - " \"type\": \"NUMERIC\"\n" +  
392 - " },\n" +  
393 - " {\n" +  
394 - " \"type\": \"COMPLEX\",\n" +  
395 - " \"operation\": \"AND\",\n" +  
396 - " \"predicates\": [\n" +  
397 - " {\n" +  
398 - " \"operation\": \"GREATER\",\n" +  
399 - " \"value\": {\n" +  
400 - " \"defaultValue\": 50,\n" +  
401 - " \"dynamicValue\": null\n" +  
402 - " },\n" +  
403 - " \"type\": \"NUMERIC\"\n" +  
404 - " },\n" +  
405 - " {\n" +  
406 - " \"operation\": \"LESS\",\n" +  
407 - " \"value\": {\n" +  
408 - " \"defaultValue\": 60,\n" +  
409 - " \"dynamicValue\": null\n" +  
410 - " },\n" +  
411 - " \"type\": \"NUMERIC\"\n" +  
412 - " }\n" +  
413 - " ]\n" +  
414 - " }\n" +  
415 - " ]\n" +  
416 - "}" +  
417 - MARKDOWN_CODE_BLOCK_END +  
418 - "\n\n You may also want to replace hardcoded values (for example, temperature > 20) with the more dynamic " +  
419 - "expression (for example, temperature > 'value of the tenant attribute with key 'temperatureThreshold'). " +  
420 - "It is possible to use 'dynamicValue' to define attribute of the tenant, customer or user that is performing the API call. " +  
421 - "See example below: \n\n" +  
422 - MARKDOWN_CODE_BLOCK_START +  
423 - "{\n" +  
424 - " \"operation\": \"GREATER\",\n" +  
425 - " \"value\": {\n" +  
426 - " \"defaultValue\": 0,\n" +  
427 - " \"dynamicValue\": {\n" +  
428 - " \"sourceType\": \"CURRENT_USER\",\n" +  
429 - " \"sourceAttribute\": \"temperatureThreshold\"\n" +  
430 - " }\n" +  
431 - " },\n" +  
432 - " \"type\": \"NUMERIC\"\n" +  
433 - "}" +  
434 - MARKDOWN_CODE_BLOCK_END +  
435 - "\n\n Note that you may use 'CURRENT_USER', 'CURRENT_CUSTOMER' and 'CURRENT_TENANT' as a 'sourceType'. The 'defaultValue' is used when the attribute with such a name is not defined for the chosen source.";  
436 -  
437 - private static final String KEY_FILTERS =  
438 - "\n\n # Key Filters" +  
439 - "\nKey Filter allows you to define complex logical expressions over entity field, attribute or latest time-series value. The filter is defined using 'key', 'valueType' and 'predicate' objects. " +  
440 - "Single Entity Query may have zero, one or multiple predicates. If multiple filters are defined, they are evaluated using logical 'AND'. " +  
441 - "The example below checks that temperature of the entity is above 20 degrees:" +  
442 - "\n\n" + MARKDOWN_CODE_BLOCK_START +  
443 - "{\n" +  
444 - " \"key\": {\n" +  
445 - " \"type\": \"TIME_SERIES\",\n" +  
446 - " \"key\": \"temperature\"\n" +  
447 - " },\n" +  
448 - " \"valueType\": \"NUMERIC\",\n" +  
449 - " \"predicate\": {\n" +  
450 - " \"operation\": \"GREATER\",\n" +  
451 - " \"value\": {\n" +  
452 - " \"defaultValue\": 20,\n" +  
453 - " \"dynamicValue\": null\n" +  
454 - " },\n" +  
455 - " \"type\": \"NUMERIC\"\n" +  
456 - " }\n" +  
457 - "}" +  
458 - MARKDOWN_CODE_BLOCK_END +  
459 - "\n\n Now let's review 'key', 'valueType' and 'predicate' objects in detail."  
460 - + FILTER_KEY + FILTER_VALUE_TYPE + FILTER_PREDICATE;  
461 -  
462 - private static final String ENTITY_COUNT_QUERY_DESCRIPTION =  
463 - "Allows to run complex queries to search the count of platform entities (devices, assets, customers, etc) " +  
464 - "based on the combination of main entity filter and multiple key filters. Returns the number of entities that match the query definition.\n\n" +  
465 - "# Query Definition\n\n" +  
466 - "\n\nMain **entity filter** is mandatory and defines generic search criteria. " +  
467 - "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +  
468 - "\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " +  
469 - "main entity fields (name, label, type, etc), attributes and telemetry. " +  
470 - "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"."+  
471 - "\n\nLet's review the example:" +  
472 - "\n\n" + MARKDOWN_CODE_BLOCK_START +  
473 - "{\n" +  
474 - " \"entityFilter\": {\n" +  
475 - " \"type\": \"entityType\",\n" +  
476 - " \"entityType\": \"DEVICE\"\n" +  
477 - " },\n" +  
478 - " \"keyFilters\": [\n" +  
479 - " {\n" +  
480 - " \"key\": {\n" +  
481 - " \"type\": \"ATTRIBUTE\",\n" +  
482 - " \"key\": \"active\"\n" +  
483 - " },\n" +  
484 - " \"valueType\": \"BOOLEAN\",\n" +  
485 - " \"predicate\": {\n" +  
486 - " \"operation\": \"EQUAL\",\n" +  
487 - " \"value\": {\n" +  
488 - " \"defaultValue\": true,\n" +  
489 - " \"dynamicValue\": null\n" +  
490 - " },\n" +  
491 - " \"type\": \"BOOLEAN\"\n" +  
492 - " }\n" +  
493 - " }\n" +  
494 - " ]\n" +  
495 - "}"+  
496 - MARKDOWN_CODE_BLOCK_END +  
497 - "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +  
498 - ENTITY_FILTERS +  
499 - KEY_FILTERS +  
500 - TENANT_OR_USER_AUTHORITY_PARAGRAPH;;  
501 -  
502 - private static final String ENTITY_DATA_QUERY_DESCRIPTION =  
503 - "Allows to run complex queries over platform entities (devices, assets, customers, etc) " +  
504 - "based on the combination of main entity filter and multiple key filters. " +  
505 - "Returns the paginated result of the query that contains requested entity fields and latest values of requested attributes and time-series data.\n\n" +  
506 - "# Query Definition\n\n" +  
507 - "\n\nMain **entity filter** is mandatory and defines generic search criteria. " +  
508 - "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +  
509 - "\n\nOptional **key filters** allow to filter results of the **entity filter** by complex criteria against " +  
510 - "main entity fields (name, label, type, etc), attributes and telemetry. " +  
511 - "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"."+  
512 - "\n\nThe **entity fields** and **latest values** contains list of entity fields and latest attribute/telemetry fields to fetch for each entity." +  
513 - "\n\nThe **page link** contains information about the page to fetch and the sort ordering." +  
514 - "\n\nLet's review the example:" +  
515 - "\n\n" + MARKDOWN_CODE_BLOCK_START +  
516 - "{\n" +  
517 - " \"entityFilter\": {\n" +  
518 - " \"type\": \"entityType\",\n" +  
519 - " \"resolveMultiple\": true,\n" +  
520 - " \"entityType\": \"DEVICE\"\n" +  
521 - " },\n" +  
522 - " \"keyFilters\": [\n" +  
523 - " {\n" +  
524 - " \"key\": {\n" +  
525 - " \"type\": \"TIME_SERIES\",\n" +  
526 - " \"key\": \"temperature\"\n" +  
527 - " },\n" +  
528 - " \"valueType\": \"NUMERIC\",\n" +  
529 - " \"predicate\": {\n" +  
530 - " \"operation\": \"GREATER\",\n" +  
531 - " \"value\": {\n" +  
532 - " \"defaultValue\": 0,\n" +  
533 - " \"dynamicValue\": {\n" +  
534 - " \"sourceType\": \"CURRENT_USER\",\n" +  
535 - " \"sourceAttribute\": \"temperatureThreshold\",\n" +  
536 - " \"inherit\": false\n" +  
537 - " }\n" +  
538 - " },\n" +  
539 - " \"type\": \"NUMERIC\"\n" +  
540 - " }\n" +  
541 - " }\n" +  
542 - " ],\n" +  
543 - " \"entityFields\": [\n" +  
544 - " {\n" +  
545 - " \"type\": \"ENTITY_FIELD\",\n" +  
546 - " \"key\": \"name\"\n" +  
547 - " },\n" +  
548 - " {\n" +  
549 - " \"type\": \"ENTITY_FIELD\",\n" +  
550 - " \"key\": \"label\"\n" +  
551 - " },\n" +  
552 - " {\n" +  
553 - " \"type\": \"ENTITY_FIELD\",\n" +  
554 - " \"key\": \"additionalInfo\"\n" +  
555 - " }\n" +  
556 - " ],\n" +  
557 - " \"latestValues\": [\n" +  
558 - " {\n" +  
559 - " \"type\": \"ATTRIBUTE\",\n" +  
560 - " \"key\": \"model\"\n" +  
561 - " },\n" +  
562 - " {\n" +  
563 - " \"type\": \"TIME_SERIES\",\n" +  
564 - " \"key\": \"temperature\"\n" +  
565 - " }\n" +  
566 - " ],\n" +  
567 - " \"pageLink\": {\n" +  
568 - " \"page\": 0,\n" +  
569 - " \"pageSize\": 10,\n" +  
570 - " \"sortOrder\": {\n" +  
571 - " \"key\": {\n" +  
572 - " \"key\": \"name\",\n" +  
573 - " \"type\": \"ENTITY_FIELD\"\n" +  
574 - " },\n" +  
575 - " \"direction\": \"ASC\"\n" +  
576 - " }\n" +  
577 - " }\n" +  
578 - "}"+  
579 - MARKDOWN_CODE_BLOCK_END +  
580 - "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +  
581 - ENTITY_FILTERS +  
582 - KEY_FILTERS +  
583 - TENANT_OR_USER_AUTHORITY_PARAGRAPH;  
584 -  
585 -  
586 - private static final String ALARM_DATA_QUERY_DESCRIPTION = "This method description defines how Alarm Data Query extends the Entity Data Query. " +  
587 - "See method 'Find Entity Data by Query' first to get the info about 'Entity Data Query'." +  
588 - "\n\n The platform will first search the entities that match the entity and key filters. Then, the platform will use 'Alarm Page Link' to filter the alarms related to those entities. " +  
589 - "Finally, platform fetch the properties of alarm that are defined in the **'alarmFields'** and combine them with the other entity, attribute and latest time-series fields to return the result. " +  
590 - "\n\n See example of the alarm query below. The query will search first 100 active alarms with type 'Temperature Alarm' or 'Fire Alarm' for any device with current temperature > 0. " +  
591 - "The query will return combination of the entity fields: name of the device, device model and latest temperature reading and alarms fields: createdTime, type, severity and status: " +  
592 - "\n\n" + MARKDOWN_CODE_BLOCK_START +  
593 - "{\n" +  
594 - " \"entityFilter\": {\n" +  
595 - " \"type\": \"entityType\",\n" +  
596 - " \"resolveMultiple\": true,\n" +  
597 - " \"entityType\": \"DEVICE\"\n" +  
598 - " },\n" +  
599 - " \"pageLink\": {\n" +  
600 - " \"page\": 0,\n" +  
601 - " \"pageSize\": 100,\n" +  
602 - " \"textSearch\": null,\n" +  
603 - " \"searchPropagatedAlarms\": false,\n" +  
604 - " \"statusList\": [\n" +  
605 - " \"ACTIVE\"\n" +  
606 - " ],\n" +  
607 - " \"severityList\": [\n" +  
608 - " \"CRITICAL\",\n" +  
609 - " \"MAJOR\"\n" +  
610 - " ],\n" +  
611 - " \"typeList\": [\n" +  
612 - " \"Temperature Alarm\",\n" +  
613 - " \"Fire Alarm\"\n" +  
614 - " ],\n" +  
615 - " \"sortOrder\": {\n" +  
616 - " \"key\": {\n" +  
617 - " \"key\": \"createdTime\",\n" +  
618 - " \"type\": \"ALARM_FIELD\"\n" +  
619 - " },\n" +  
620 - " \"direction\": \"DESC\"\n" +  
621 - " },\n" +  
622 - " \"timeWindow\": 86400000\n" +  
623 - " },\n" +  
624 - " \"keyFilters\": [\n" +  
625 - " {\n" +  
626 - " \"key\": {\n" +  
627 - " \"type\": \"TIME_SERIES\",\n" +  
628 - " \"key\": \"temperature\"\n" +  
629 - " },\n" +  
630 - " \"valueType\": \"NUMERIC\",\n" +  
631 - " \"predicate\": {\n" +  
632 - " \"operation\": \"GREATER\",\n" +  
633 - " \"value\": {\n" +  
634 - " \"defaultValue\": 0,\n" +  
635 - " \"dynamicValue\": null\n" +  
636 - " },\n" +  
637 - " \"type\": \"NUMERIC\"\n" +  
638 - " }\n" +  
639 - " }\n" +  
640 - " ],\n" +  
641 - " \"alarmFields\": [\n" +  
642 - " {\n" +  
643 - " \"type\": \"ALARM_FIELD\",\n" +  
644 - " \"key\": \"createdTime\"\n" +  
645 - " },\n" +  
646 - " {\n" +  
647 - " \"type\": \"ALARM_FIELD\",\n" +  
648 - " \"key\": \"type\"\n" +  
649 - " },\n" +  
650 - " {\n" +  
651 - " \"type\": \"ALARM_FIELD\",\n" +  
652 - " \"key\": \"severity\"\n" +  
653 - " },\n" +  
654 - " {\n" +  
655 - " \"type\": \"ALARM_FIELD\",\n" +  
656 - " \"key\": \"status\"\n" +  
657 - " }\n" +  
658 - " ],\n" +  
659 - " \"entityFields\": [\n" +  
660 - " {\n" +  
661 - " \"type\": \"ENTITY_FIELD\",\n" +  
662 - " \"key\": \"name\"\n" +  
663 - " }\n" +  
664 - " ],\n" +  
665 - " \"latestValues\": [\n" +  
666 - " {\n" +  
667 - " \"type\": \"ATTRIBUTE\",\n" +  
668 - " \"key\": \"model\"\n" +  
669 - " },\n" +  
670 - " {\n" +  
671 - " \"type\": \"TIME_SERIES\",\n" +  
672 - " \"key\": \"temperature\"\n" +  
673 - " }\n" +  
674 - " ]\n" +  
675 - "}"+  
676 - MARKDOWN_CODE_BLOCK_END +  
677 - "";  
678 -  
679 @Autowired 51 @Autowired
680 private EntityQueryService entityQueryService; 52 private EntityQueryService entityQueryService;
681 53
@@ -43,6 +43,11 @@ import org.thingsboard.server.service.security.permission.Operation; @@ -43,6 +43,11 @@ import org.thingsboard.server.service.security.permission.Operation;
43 import java.util.List; 43 import java.util.List;
44 import java.util.stream.Collectors; 44 import java.util.stream.Collectors;
45 45
  46 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION;
  47 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_PARAM_DESCRIPTION;
  48 +import static org.thingsboard.server.controller.ControllerConstants.RELATION_INFO_DESCRIPTION;
  49 +import static org.thingsboard.server.controller.ControllerConstants.RELATION_TYPE_GROUP_PARAM_DESCRIPTION;
  50 +import static org.thingsboard.server.controller.ControllerConstants.RELATION_TYPE_PARAM_DESCRIPTION;
46 51
47 @RestController 52 @RestController
48 @TbCoreComponent 53 @TbCoreComponent
@@ -74,6 +74,11 @@ import java.util.concurrent.ExecutionException; @@ -74,6 +74,11 @@ import java.util.concurrent.ExecutionException;
74 import java.util.stream.Collectors; 74 import java.util.stream.Collectors;
75 75
76 import static org.apache.commons.lang3.StringUtils.isBlank; 76 import static org.apache.commons.lang3.StringUtils.isBlank;
  77 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID;
  78 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  79 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
  80 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  81 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
77 import static org.thingsboard.server.controller.EdgeController.EDGE_ID; 82 import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
78 83
79 /** 84 /**
@@ -28,7 +28,7 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -28,7 +28,7 @@ import org.springframework.web.bind.annotation.RequestParam;
28 import org.springframework.web.bind.annotation.ResponseBody; 28 import org.springframework.web.bind.annotation.ResponseBody;
29 import org.springframework.web.bind.annotation.RestController; 29 import org.springframework.web.bind.annotation.RestController;
30 import org.thingsboard.server.common.data.Event; 30 import org.thingsboard.server.common.data.Event;
31 -import org.thingsboard.server.common.data.event.BaseEventFilter; 31 +import org.thingsboard.server.common.data.event.EventFilter;
32 import org.thingsboard.server.common.data.exception.ThingsboardException; 32 import org.thingsboard.server.common.data.exception.ThingsboardException;
33 import org.thingsboard.server.common.data.id.EntityId; 33 import org.thingsboard.server.common.data.id.EntityId;
34 import org.thingsboard.server.common.data.id.EntityIdFactory; 34 import org.thingsboard.server.common.data.id.EntityIdFactory;
@@ -40,13 +40,34 @@ import org.thingsboard.server.dao.model.ModelConstants; @@ -40,13 +40,34 @@ import org.thingsboard.server.dao.model.ModelConstants;
40 import org.thingsboard.server.queue.util.TbCoreComponent; 40 import org.thingsboard.server.queue.util.TbCoreComponent;
41 import org.thingsboard.server.service.security.permission.Operation; 41 import org.thingsboard.server.service.security.permission.Operation;
42 42
  43 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID;
  44 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION;
  45 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE;
  46 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_PARAM_DESCRIPTION;
  47 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ;
  48 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_DEBUG_RULE_NODE_FILTER_OBJ;
  49 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_END_TIME_DESCRIPTION;
  50 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_ERROR_FILTER_OBJ;
  51 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_LC_EVENT_FILTER_OBJ;
  52 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_SORT_PROPERTY_ALLOWABLE_VALUES;
  53 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_START_TIME_DESCRIPTION;
  54 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_STATS_FILTER_OBJ;
  55 +import static org.thingsboard.server.controller.ControllerConstants.EVENT_TEXT_SEARCH_DESCRIPTION;
  56 +import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
  57 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  58 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  59 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  60 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  61 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  62 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  63 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID;
  64 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION;
  65 +
43 @RestController 66 @RestController
44 @TbCoreComponent 67 @TbCoreComponent
45 @RequestMapping("/api") 68 @RequestMapping("/api")
46 public class EventController extends BaseController { 69 public class EventController extends BaseController {
47 70
48 - private static final String NEW_LINE = "\n\n";  
49 -  
50 @Autowired 71 @Autowired
51 private EventService eventService; 72 private EventService eventService;
52 73
@@ -162,7 +183,7 @@ public class EventController extends BaseController { @@ -162,7 +183,7 @@ public class EventController extends BaseController {
162 @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) 183 @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
163 @RequestParam int page, 184 @RequestParam int page,
164 @ApiParam(value = "A JSON value representing the event filter.", required = true) 185 @ApiParam(value = "A JSON value representing the event filter.", required = true)
165 - @RequestBody BaseEventFilter eventFilter, 186 + @RequestBody EventFilter eventFilter,
166 @ApiParam(value = EVENT_TEXT_SEARCH_DESCRIPTION) 187 @ApiParam(value = EVENT_TEXT_SEARCH_DESCRIPTION)
167 @RequestParam(required = false) String textSearch, 188 @RequestParam(required = false) String textSearch,
168 @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EVENT_SORT_PROPERTY_ALLOWABLE_VALUES) 189 @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EVENT_SORT_PROPERTY_ALLOWABLE_VALUES)
@@ -36,6 +36,9 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -36,6 +36,9 @@ import org.thingsboard.server.service.security.permission.Resource;
36 36
37 import java.util.List; 37 import java.util.List;
38 38
  39 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
  40 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
  41 +
39 @RestController 42 @RestController
40 @TbCoreComponent 43 @TbCoreComponent
41 @RequestMapping("/api/oauth2/config/template") 44 @RequestMapping("/api/oauth2/config/template")
@@ -45,7 +48,7 @@ public class OAuth2ConfigTemplateController extends BaseController { @@ -45,7 +48,7 @@ public class OAuth2ConfigTemplateController extends BaseController {
45 48
46 private static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION = "Client registration template is OAuth2 provider configuration template with default settings for registering new OAuth2 clients"; 49 private static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION = "Client registration template is OAuth2 provider configuration template with default settings for registering new OAuth2 clients";
47 50
48 - @ApiOperation(value = "Create or update OAuth2 client registration template (saveClientRegistrationTemplate)", 51 + @ApiOperation(value = "Create or update OAuth2 client registration template (saveClientRegistrationTemplate)" + SYSTEM_AUTHORITY_PARAGRAPH,
49 notes = OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION) 52 notes = OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION)
50 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 53 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
51 @RequestMapping(method = RequestMethod.POST) 54 @RequestMapping(method = RequestMethod.POST)
@@ -59,7 +62,7 @@ public class OAuth2ConfigTemplateController extends BaseController { @@ -59,7 +62,7 @@ public class OAuth2ConfigTemplateController extends BaseController {
59 } 62 }
60 } 63 }
61 64
62 - @ApiOperation(value = "Delete OAuth2 client registration template by id (deleteClientRegistrationTemplate)", 65 + @ApiOperation(value = "Delete OAuth2 client registration template by id (deleteClientRegistrationTemplate)" + SYSTEM_AUTHORITY_PARAGRAPH,
63 notes = OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION) 66 notes = OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION)
64 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 67 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
65 @RequestMapping(value = "/{clientRegistrationTemplateId}", method = RequestMethod.DELETE) 68 @RequestMapping(value = "/{clientRegistrationTemplateId}", method = RequestMethod.DELETE)
@@ -76,7 +79,7 @@ public class OAuth2ConfigTemplateController extends BaseController { @@ -76,7 +79,7 @@ public class OAuth2ConfigTemplateController extends BaseController {
76 } 79 }
77 } 80 }
78 81
79 - @ApiOperation(value = "Get the list of all OAuth2 client registration templates (getClientRegistrationTemplates)", 82 + @ApiOperation(value = "Get the list of all OAuth2 client registration templates (getClientRegistrationTemplates)" + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH,
80 notes = OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION) 83 notes = OAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION)
81 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 84 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
82 @RequestMapping(method = RequestMethod.GET, produces = "application/json") 85 @RequestMapping(method = RequestMethod.GET, produces = "application/json")
@@ -43,6 +43,8 @@ import javax.servlet.http.HttpServletRequest; @@ -43,6 +43,8 @@ import javax.servlet.http.HttpServletRequest;
43 import java.util.Enumeration; 43 import java.util.Enumeration;
44 import java.util.List; 44 import java.util.List;
45 45
  46 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
  47 +
46 @RestController 48 @RestController
47 @TbCoreComponent 49 @TbCoreComponent
48 @RequestMapping("/api") 50 @RequestMapping("/api")
@@ -88,7 +90,7 @@ public class OAuth2Controller extends BaseController { @@ -88,7 +90,7 @@ public class OAuth2Controller extends BaseController {
88 } 90 }
89 } 91 }
90 92
91 - @ApiOperation(value = "Get current OAuth2 settings (getCurrentOAuth2Info)") 93 + @ApiOperation(value = "Get current OAuth2 settings (getCurrentOAuth2Info)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
92 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 94 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
93 @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json") 95 @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json")
94 @ResponseBody 96 @ResponseBody
@@ -101,7 +103,7 @@ public class OAuth2Controller extends BaseController { @@ -101,7 +103,7 @@ public class OAuth2Controller extends BaseController {
101 } 103 }
102 } 104 }
103 105
104 - @ApiOperation(value = "Save OAuth2 settings (saveOAuth2Info)") 106 + @ApiOperation(value = "Save OAuth2 settings (saveOAuth2Info)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
105 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 107 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
106 @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST) 108 @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST)
107 @ResponseStatus(value = HttpStatus.OK) 109 @ResponseStatus(value = HttpStatus.OK)
@@ -118,7 +120,7 @@ public class OAuth2Controller extends BaseController { @@ -118,7 +120,7 @@ public class OAuth2Controller extends BaseController {
118 @ApiOperation(value = "Get OAuth2 log in processing URL (getLoginProcessingUrl)", notes = "Returns the URL enclosed in " + 120 @ApiOperation(value = "Get OAuth2 log in processing URL (getLoginProcessingUrl)", notes = "Returns the URL enclosed in " +
119 "double quotes. After successful authentication with OAuth2 provider, it makes a redirect to this path so that the platform can do " + 121 "double quotes. After successful authentication with OAuth2 provider, it makes a redirect to this path so that the platform can do " +
120 "further log in processing. This URL may be configured as 'security.oauth2.loginProcessingUrl' property in yml configuration file, or " + 122 "further log in processing. This URL may be configured as 'security.oauth2.loginProcessingUrl' property in yml configuration file, or " +
121 - "as 'SECURITY_OAUTH2_LOGIN_PROCESSING_URL' env variable. By default it is '/login/oauth2/code/'") 123 + "as 'SECURITY_OAUTH2_LOGIN_PROCESSING_URL' env variable. By default it is '/login/oauth2/code/'" + SYSTEM_AUTHORITY_PARAGRAPH)
122 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") 124 @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
123 @RequestMapping(value = "/oauth2/loginProcessingUrl", method = RequestMethod.GET) 125 @RequestMapping(value = "/oauth2/loginProcessingUrl", method = RequestMethod.GET)
124 @ResponseBody 126 @ResponseBody
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import io.swagger.annotations.ApiOperation;
  19 +import io.swagger.annotations.ApiParam;
18 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
19 import org.apache.commons.lang3.StringUtils; 21 import org.apache.commons.lang3.StringUtils;
20 import org.springframework.core.io.ByteArrayResource; 22 import org.springframework.core.io.ByteArrayResource;
@@ -47,6 +49,22 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -47,6 +49,22 @@ import org.thingsboard.server.service.security.permission.Resource;
47 49
48 import java.nio.ByteBuffer; 50 import java.nio.ByteBuffer;
49 51
  52 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID_PARAM_DESCRIPTION;
  53 +import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_CHECKSUM_ALGORITHM_ALLOWABLE_VALUES;
  54 +import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_DESCRIPTION;
  55 +import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_ID_PARAM_DESCRIPTION;
  56 +import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_INFO_DESCRIPTION;
  57 +import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES;
  58 +import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION;
  59 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  60 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  61 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  62 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  63 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  64 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  65 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  66 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  67 +
50 @Slf4j 68 @Slf4j
51 @RestController 69 @RestController
52 @TbCoreComponent 70 @TbCoreComponent
@@ -56,10 +74,12 @@ public class OtaPackageController extends BaseController { @@ -56,10 +74,12 @@ public class OtaPackageController extends BaseController {
56 public static final String OTA_PACKAGE_ID = "otaPackageId"; 74 public static final String OTA_PACKAGE_ID = "otaPackageId";
57 public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm"; 75 public static final String CHECKSUM_ALGORITHM = "checksumAlgorithm";
58 76
  77 + @ApiOperation(value = "Download OTA Package (downloadOtaPackage)", notes = "Download OTA Package based on the provided OTA Package Id." + TENANT_AUTHORITY_PARAGRAPH)
59 @PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')") 78 @PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')")
60 @RequestMapping(value = "/otaPackage/{otaPackageId}/download", method = RequestMethod.GET) 79 @RequestMapping(value = "/otaPackage/{otaPackageId}/download", method = RequestMethod.GET)
61 @ResponseBody 80 @ResponseBody
62 - public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { 81 + public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
  82 + @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
63 checkParameter(OTA_PACKAGE_ID, strOtaPackageId); 83 checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
64 try { 84 try {
65 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); 85 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
@@ -81,10 +101,15 @@ public class OtaPackageController extends BaseController { @@ -81,10 +101,15 @@ public class OtaPackageController extends BaseController {
81 } 101 }
82 } 102 }
83 103
  104 + @ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)",
  105 + notes = "Fetch the OTA Package Info object based on the provided OTA Package Id. " +
  106 + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  107 + produces = "application/json")
84 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 108 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
85 @RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET) 109 @RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET)
86 @ResponseBody 110 @ResponseBody
87 - public OtaPackageInfo getOtaPackageInfoById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { 111 + public OtaPackageInfo getOtaPackageInfoById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
  112 + @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
88 checkParameter(OTA_PACKAGE_ID, strOtaPackageId); 113 checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
89 try { 114 try {
90 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); 115 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
@@ -94,10 +119,15 @@ public class OtaPackageController extends BaseController { @@ -94,10 +119,15 @@ public class OtaPackageController extends BaseController {
94 } 119 }
95 } 120 }
96 121
  122 + @ApiOperation(value = "Get OTA Package (getOtaPackageById)",
  123 + notes = "Fetch the OTA Package object based on the provided OTA Package Id. " +
  124 + "The server checks that the OTA Package is owned by the same tenant. " + OTA_PACKAGE_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH,
  125 + produces = "application/json")
97 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 126 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
98 @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET) 127 @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET)
99 @ResponseBody 128 @ResponseBody
100 - public OtaPackage getOtaPackageById(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { 129 + public OtaPackage getOtaPackageById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
  130 + @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
101 checkParameter(OTA_PACKAGE_ID, strOtaPackageId); 131 checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
102 try { 132 try {
103 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); 133 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
@@ -107,10 +137,19 @@ public class OtaPackageController extends BaseController { @@ -107,10 +137,19 @@ public class OtaPackageController extends BaseController {
107 } 137 }
108 } 138 }
109 139
  140 + @ApiOperation(value = "Create Or Update OTA Package Info (saveOtaPackageInfo)",
  141 + notes = "Create or update the OTA Package Info. When creating OTA Package Info, platform generates OTA Package id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  142 + "The newly created OTA Package id will be present in the response. " +
  143 + "Specify existing OTA Package id to update the OTA Package Info. " +
  144 + "Referencing non-existing OTA Package Id will cause 'Not Found' error. " +
  145 + "\n\nOTA Package combination of the title with the version is unique in the scope of tenant. " + TENANT_AUTHORITY_PARAGRAPH,
  146 + produces = "application/json",
  147 + consumes = "application/json")
110 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 148 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
111 @RequestMapping(value = "/otaPackage", method = RequestMethod.POST) 149 @RequestMapping(value = "/otaPackage", method = RequestMethod.POST)
112 @ResponseBody 150 @ResponseBody
113 - public OtaPackageInfo saveOtaPackageInfo(@RequestBody SaveOtaPackageInfoRequest otaPackageInfo) throws ThingsboardException { 151 + public OtaPackageInfo saveOtaPackageInfo(@ApiParam(value = "A JSON value representing the OTA Package.")
  152 + @RequestBody SaveOtaPackageInfoRequest otaPackageInfo) throws ThingsboardException {
114 boolean created = otaPackageInfo.getId() == null; 153 boolean created = otaPackageInfo.getId() == null;
115 try { 154 try {
116 otaPackageInfo.setTenantId(getTenantId()); 155 otaPackageInfo.setTenantId(getTenantId());
@@ -126,13 +165,20 @@ public class OtaPackageController extends BaseController { @@ -126,13 +165,20 @@ public class OtaPackageController extends BaseController {
126 } 165 }
127 } 166 }
128 167
  168 + @ApiOperation(value = "Save OTA Package data (saveOtaPackageData)",
  169 + notes = "Update the OTA Package. Adds the date to the existing OTA Package Info" + TENANT_AUTHORITY_PARAGRAPH,
  170 + produces = "application/json")
129 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 171 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
130 @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST) 172 @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST)
131 @ResponseBody 173 @ResponseBody
132 - public OtaPackageInfo saveOtaPackageData(@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId,  
133 - @RequestParam(required = false) String checksum,  
134 - @RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,  
135 - @RequestBody MultipartFile file) throws ThingsboardException { 174 + public OtaPackageInfo saveOtaPackageData(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
  175 + @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId,
  176 + @ApiParam(value = "OTA Package checksum. For example, '0xd87f7e0c'")
  177 + @RequestParam(required = false) String checksum,
  178 + @ApiParam(value = "OTA Package checksum algorithm.", allowableValues = OTA_PACKAGE_CHECKSUM_ALGORITHM_ALLOWABLE_VALUES)
  179 + @RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr,
  180 + @ApiParam(value = "OTA Package data.")
  181 + @RequestBody MultipartFile file) throws ThingsboardException {
136 checkParameter(OTA_PACKAGE_ID, strOtaPackageId); 182 checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
137 checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr); 183 checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr);
138 try { 184 try {
@@ -171,14 +217,23 @@ public class OtaPackageController extends BaseController { @@ -171,14 +217,23 @@ public class OtaPackageController extends BaseController {
171 } 217 }
172 } 218 }
173 219
  220 + @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)",
  221 + notes = "Returns a page of OTA Package Info objects owned by tenant. " +
  222 + PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  223 + produces = "application/json")
174 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 224 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
175 @RequestMapping(value = "/otaPackages", method = RequestMethod.GET) 225 @RequestMapping(value = "/otaPackages", method = RequestMethod.GET)
176 @ResponseBody 226 @ResponseBody
177 - public PageData<OtaPackageInfo> getOtaPackages(@RequestParam int pageSize,  
178 - @RequestParam int page,  
179 - @RequestParam(required = false) String textSearch,  
180 - @RequestParam(required = false) String sortProperty,  
181 - @RequestParam(required = false) String sortOrder) throws ThingsboardException { 227 + public PageData<OtaPackageInfo> getOtaPackages(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
  228 + @RequestParam int pageSize,
  229 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
  230 + @RequestParam int page,
  231 + @ApiParam(value = OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION)
  232 + @RequestParam(required = false) String textSearch,
  233 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES)
  234 + @RequestParam(required = false) String sortProperty,
  235 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
  236 + @RequestParam(required = false) String sortOrder) throws ThingsboardException {
182 try { 237 try {
183 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); 238 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
184 return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink)); 239 return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink));
@@ -187,15 +242,26 @@ public class OtaPackageController extends BaseController { @@ -187,15 +242,26 @@ public class OtaPackageController extends BaseController {
187 } 242 }
188 } 243 }
189 244
  245 + @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)",
  246 + notes = "Returns a page of OTA Package Info objects owned by tenant. " +
  247 + PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  248 + produces = "application/json")
190 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 249 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
191 @RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}", method = RequestMethod.GET) 250 @RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}", method = RequestMethod.GET)
192 @ResponseBody 251 @ResponseBody
193 - public PageData<OtaPackageInfo> getOtaPackages(@PathVariable("deviceProfileId") String strDeviceProfileId, 252 + public PageData<OtaPackageInfo> getOtaPackages(@ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION)
  253 + @PathVariable("deviceProfileId") String strDeviceProfileId,
  254 + @ApiParam(value = "OTA Package type.", allowableValues = "FIRMWARE, SOFTWARE")
194 @PathVariable("type") String strType, 255 @PathVariable("type") String strType,
  256 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
195 @RequestParam int pageSize, 257 @RequestParam int pageSize,
  258 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
196 @RequestParam int page, 259 @RequestParam int page,
  260 + @ApiParam(value = OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION)
197 @RequestParam(required = false) String textSearch, 261 @RequestParam(required = false) String textSearch,
  262 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES)
198 @RequestParam(required = false) String sortProperty, 263 @RequestParam(required = false) String sortProperty,
  264 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
199 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 265 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
200 checkParameter("deviceProfileId", strDeviceProfileId); 266 checkParameter("deviceProfileId", strDeviceProfileId);
201 checkParameter("type", strType); 267 checkParameter("type", strType);
@@ -208,10 +274,15 @@ public class OtaPackageController extends BaseController { @@ -208,10 +274,15 @@ public class OtaPackageController extends BaseController {
208 } 274 }
209 } 275 }
210 276
  277 + @ApiOperation(value = "Delete OTA Package (deleteOtaPackage)",
  278 + notes = "Deletes the OTA Package. Referencing non-existing OTA Package Id will cause an error. " +
  279 + "Can't delete the OTA Package if it is referenced by existing devices or device profile." + TENANT_AUTHORITY_PARAGRAPH,
  280 + produces = "application/json")
211 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 281 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
212 @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE) 282 @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE)
213 @ResponseBody 283 @ResponseBody
214 - public void deleteOtaPackage(@PathVariable("otaPackageId") String strOtaPackageId) throws ThingsboardException { 284 + public void deleteOtaPackage(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
  285 + @PathVariable("otaPackageId") String strOtaPackageId) throws ThingsboardException {
215 checkParameter(OTA_PACKAGE_ID, strOtaPackageId); 286 checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
216 try { 287 try {
217 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); 288 OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
@@ -15,7 +15,10 @@ @@ -15,7 +15,10 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import io.swagger.annotations.ApiOperation;
  19 +import io.swagger.annotations.ApiParam;
18 import lombok.RequiredArgsConstructor; 20 import lombok.RequiredArgsConstructor;
  21 +import org.springframework.http.MediaType;
19 import org.springframework.security.access.prepost.PreAuthorize; 22 import org.springframework.security.access.prepost.PreAuthorize;
20 import org.springframework.web.bind.annotation.RequestMapping; 23 import org.springframework.web.bind.annotation.RequestMapping;
21 import org.springframework.web.bind.annotation.RequestMethod; 24 import org.springframework.web.bind.annotation.RequestMethod;
@@ -29,6 +32,10 @@ import org.thingsboard.server.queue.util.TbCoreComponent; @@ -29,6 +32,10 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
29 32
30 import java.util.Set; 33 import java.util.Set;
31 34
  35 +import static org.thingsboard.server.controller.ControllerConstants.QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES;
  36 +import static org.thingsboard.server.controller.ControllerConstants.QUEUE_SERVICE_TYPE_DESCRIPTION;
  37 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  38 +
32 @RestController 39 @RestController
33 @TbCoreComponent 40 @TbCoreComponent
34 @RequestMapping("/api") 41 @RequestMapping("/api")
@@ -37,10 +44,13 @@ public class QueueController extends BaseController { @@ -37,10 +44,13 @@ public class QueueController extends BaseController {
37 44
38 private final QueueService queueService; 45 private final QueueService queueService;
39 46
  47 + @ApiOperation(value = "Get queue names (getTenantQueuesByServiceType)",
  48 + notes = "Returns a set of unique queue names based on service type. " + TENANT_AUTHORITY_PARAGRAPH)
40 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 49 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
41 - @RequestMapping(value = "/tenant/queues", params = {"serviceType"}, method = RequestMethod.GET)  
42 - @ResponseBody  
43 - public Set<String> getTenantQueuesByServiceType(@RequestParam String serviceType) throws ThingsboardException { 50 + @RequestMapping(value = "/tenant/queues", params = {"serviceType"}, produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
  51 + @ResponseBody()
  52 + public Set<String> getTenantQueuesByServiceType(@ApiParam(value = QUEUE_SERVICE_TYPE_DESCRIPTION, allowableValues = QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES)
  53 + @RequestParam String serviceType) throws ThingsboardException {
44 checkParameter("serviceType", serviceType); 54 checkParameter("serviceType", serviceType);
45 try { 55 try {
46 return queueService.getQueuesByServiceType(ServiceType.valueOf(serviceType)); 56 return queueService.getQueuesByServiceType(ServiceType.valueOf(serviceType));
@@ -34,13 +34,16 @@ import org.thingsboard.server.queue.util.TbCoreComponent; @@ -34,13 +34,16 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
34 34
35 import java.util.UUID; 35 import java.util.UUID;
36 36
  37 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION;
  38 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  39 +
37 @RestController 40 @RestController
38 @TbCoreComponent 41 @TbCoreComponent
39 @RequestMapping(TbUrlConstants.RPC_V1_URL_PREFIX) 42 @RequestMapping(TbUrlConstants.RPC_V1_URL_PREFIX)
40 @Slf4j 43 @Slf4j
41 public class RpcV1Controller extends AbstractRpcController { 44 public class RpcV1Controller extends AbstractRpcController {
42 45
43 - @ApiOperation(value = "Send one-way RPC request (handleOneWayDeviceRPCRequest)", notes = "Deprecated. See 'Rpc V 2 Controller' instead.") 46 + @ApiOperation(value = "Send one-way RPC request (handleOneWayDeviceRPCRequest)", notes = "Deprecated. See 'Rpc V 2 Controller' instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
44 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 47 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
45 @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) 48 @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
46 @ResponseBody 49 @ResponseBody
@@ -52,7 +55,7 @@ public class RpcV1Controller extends AbstractRpcController { @@ -52,7 +55,7 @@ public class RpcV1Controller extends AbstractRpcController {
52 return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT); 55 return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT);
53 } 56 }
54 57
55 - @ApiOperation(value = "Send two-way RPC request (handleTwoWayDeviceRPCRequest)", notes = "Deprecated. See 'Rpc V 2 Controller' instead.") 58 + @ApiOperation(value = "Send two-way RPC request (handleTwoWayDeviceRPCRequest)", notes = "Deprecated. See 'Rpc V 2 Controller' instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
56 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 59 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
57 @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) 60 @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
58 @ResponseBody 61 @ResponseBody
@@ -53,6 +53,8 @@ import java.util.UUID; @@ -53,6 +53,8 @@ import java.util.UUID;
53 53
54 import static org.thingsboard.server.common.data.DataConstants.RPC_DELETED; 54 import static org.thingsboard.server.common.data.DataConstants.RPC_DELETED;
55 55
  56 +import static org.thingsboard.server.controller.ControllerConstants.*;
  57 +
56 @RestController 58 @RestController
57 @TbCoreComponent 59 @TbCoreComponent
58 @RequestMapping(TbUrlConstants.RPC_V2_URL_PREFIX) 60 @RequestMapping(TbUrlConstants.RPC_V2_URL_PREFIX)
@@ -94,9 +96,9 @@ public class RpcV2Controller extends AbstractRpcController { @@ -94,9 +96,9 @@ public class RpcV2Controller extends AbstractRpcController {
94 "In case of persistent RPC, the result of this call is 'rpcId' UUID. In case of lightweight RPC, " + 96 "In case of persistent RPC, the result of this call is 'rpcId' UUID. In case of lightweight RPC, " +
95 "the result of this call is the response from device, or 504 Gateway Timeout if device is offline."; 97 "the result of this call is the response from device, or 504 Gateway Timeout if device is offline.";
96 98
97 - private static final String ONE_WAY_RPC_REQUEST_DESCRIPTION = "Sends the one-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + ONE_WAY_RPC_RESULT + TENANT_OR_USER_AUTHORITY_PARAGRAPH; 99 + private static final String ONE_WAY_RPC_REQUEST_DESCRIPTION = "Sends the one-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + ONE_WAY_RPC_RESULT + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
98 100
99 - private static final String TWO_WAY_RPC_REQUEST_DESCRIPTION = "Sends the two-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + TWO_WAY_RPC_RESULT + TENANT_OR_USER_AUTHORITY_PARAGRAPH; 101 + private static final String TWO_WAY_RPC_REQUEST_DESCRIPTION = "Sends the two-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + TWO_WAY_RPC_RESULT + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
100 102
101 @ApiOperation(value = "Send one-way RPC request", notes = ONE_WAY_RPC_REQUEST_DESCRIPTION) 103 @ApiOperation(value = "Send one-way RPC request", notes = ONE_WAY_RPC_REQUEST_DESCRIPTION)
102 @ApiResponses(value = { 104 @ApiResponses(value = {
@@ -134,7 +136,7 @@ public class RpcV2Controller extends AbstractRpcController { @@ -134,7 +136,7 @@ public class RpcV2Controller extends AbstractRpcController {
134 return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT); 136 return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT);
135 } 137 }
136 138
137 - @ApiOperation(value = "Get persistent RPC request", notes = "Get information about the status of the RPC call." + TENANT_OR_USER_AUTHORITY_PARAGRAPH) 139 + @ApiOperation(value = "Get persistent RPC request", notes = "Get information about the status of the RPC call." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
138 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 140 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
139 @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET) 141 @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET)
140 @ResponseBody 142 @ResponseBody
@@ -150,7 +152,7 @@ public class RpcV2Controller extends AbstractRpcController { @@ -150,7 +152,7 @@ public class RpcV2Controller extends AbstractRpcController {
150 } 152 }
151 } 153 }
152 154
153 - @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_OR_USER_AUTHORITY_PARAGRAPH) 155 + @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
154 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 156 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
155 @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET) 157 @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET)
156 @ResponseBody 158 @ResponseBody
@@ -81,6 +81,25 @@ import java.util.concurrent.ConcurrentMap; @@ -81,6 +81,25 @@ import java.util.concurrent.ConcurrentMap;
81 import java.util.concurrent.TimeUnit; 81 import java.util.concurrent.TimeUnit;
82 import java.util.stream.Collectors; 82 import java.util.stream.Collectors;
83 83
  84 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  85 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
  86 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
  87 +import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION;
  88 +import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END;
  89 +import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_START;
  90 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  91 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  92 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  93 +import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_ID_PARAM_DESCRIPTION;
  94 +import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES;
  95 +import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TEXT_SEARCH_DESCRIPTION;
  96 +import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPES_ALLOWABLE_VALUES;
  97 +import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPE_DESCRIPTION;
  98 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  99 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  100 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  101 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  102 +
84 @Slf4j 103 @Slf4j
85 @RestController 104 @RestController
86 @TbCoreComponent 105 @TbCoreComponent
@@ -169,7 +188,7 @@ public class RuleChainController extends BaseController { @@ -169,7 +188,7 @@ public class RuleChainController extends BaseController {
169 "The newly created Rule Chain Id will be present in the response. " + 188 "The newly created Rule Chain Id will be present in the response. " +
170 "Specify existing Rule Chain id to update the rule chain. " + 189 "Specify existing Rule Chain id to update the rule chain. " +
171 "Referencing non-existing rule chain Id will cause 'Not Found' error." + 190 "Referencing non-existing rule chain Id will cause 'Not Found' error." +
172 - "\n\n" + RULE_CHAIN_DESCRIPTION) 191 + "\n\n" + RULE_CHAIN_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
173 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 192 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
174 @RequestMapping(value = "/ruleChain", method = RequestMethod.POST) 193 @RequestMapping(value = "/ruleChain", method = RequestMethod.POST)
175 @ResponseBody 194 @ResponseBody
@@ -327,7 +346,7 @@ public class RuleChainController extends BaseController { @@ -327,7 +346,7 @@ public class RuleChainController extends BaseController {
327 346
328 347
329 @ApiOperation(value = "Get Rule Chains (getRuleChains)", 348 @ApiOperation(value = "Get Rule Chains (getRuleChains)",
330 - notes = "Returns a page of Rule Chains owned by tenant. " + RULE_CHAIN_DESCRIPTION + PAGE_DATA_PARAMETERS) 349 + notes = "Returns a page of Rule Chains owned by tenant. " + RULE_CHAIN_DESCRIPTION + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
331 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 350 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
332 @RequestMapping(value = "/ruleChains", params = {"pageSize", "page"}, method = RequestMethod.GET) 351 @RequestMapping(value = "/ruleChains", params = {"pageSize", "page"}, method = RequestMethod.GET)
333 @ResponseBody 352 @ResponseBody
@@ -358,7 +377,8 @@ public class RuleChainController extends BaseController { @@ -358,7 +377,8 @@ public class RuleChainController extends BaseController {
358 } 377 }
359 378
360 @ApiOperation(value = "Delete rule chain (deleteRuleChain)", 379 @ApiOperation(value = "Delete rule chain (deleteRuleChain)",
361 - notes = "Deletes the rule chain. Referencing non-existing rule chain Id will cause an error. Referencing rule chain that is used in the device profiles will cause an error.") 380 + notes = "Deletes the rule chain. Referencing non-existing rule chain Id will cause an error. " +
  381 + "Referencing rule chain that is used in the device profiles will cause an error." + TENANT_AUTHORITY_PARAGRAPH)
362 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 382 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
363 @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) 383 @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.DELETE)
364 @ResponseStatus(value = HttpStatus.OK) 384 @ResponseStatus(value = HttpStatus.OK)
@@ -409,7 +429,7 @@ public class RuleChainController extends BaseController { @@ -409,7 +429,7 @@ public class RuleChainController extends BaseController {
409 429
410 @ApiOperation(value = "Get latest input message (getLatestRuleNodeDebugInput)", 430 @ApiOperation(value = "Get latest input message (getLatestRuleNodeDebugInput)",
411 notes = "Gets the input message from the debug events for specified Rule Chain Id. " + 431 notes = "Gets the input message from the debug events for specified Rule Chain Id. " +
412 - "Referencing non-existing rule chain Id will cause an error. ") 432 + "Referencing non-existing rule chain Id will cause an error. " + TENANT_AUTHORITY_PARAGRAPH)
413 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 433 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
414 @RequestMapping(value = "/ruleNode/{ruleNodeId}/debugIn", method = RequestMethod.GET) 434 @RequestMapping(value = "/ruleNode/{ruleNodeId}/debugIn", method = RequestMethod.GET)
415 @ResponseBody 435 @ResponseBody
@@ -582,7 +602,7 @@ public class RuleChainController extends BaseController { @@ -582,7 +602,7 @@ public class RuleChainController extends BaseController {
582 "Second, remote edge service will receive a copy of assignment rule chain " + 602 "Second, remote edge service will receive a copy of assignment rule chain " +
583 EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + ". " + 603 EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + ". " +
584 "Third, once rule chain will be delivered to edge service, it's going to start processing messages locally. " + 604 "Third, once rule chain will be delivered to edge service, it's going to start processing messages locally. " +
585 - "\n\nOnly rule chain with type 'EDGE' can be assigned to edge.", 605 + "\n\nOnly rule chain with type 'EDGE' can be assigned to edge." + TENANT_AUTHORITY_PARAGRAPH,
586 produces = MediaType.APPLICATION_JSON_VALUE) 606 produces = MediaType.APPLICATION_JSON_VALUE)
587 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 607 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
588 @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.POST) 608 @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.POST)
@@ -622,7 +642,7 @@ public class RuleChainController extends BaseController { @@ -622,7 +642,7 @@ public class RuleChainController extends BaseController {
622 EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + 642 EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
623 "Second, remote edge service will receive an 'unassign' command to remove rule chain " + 643 "Second, remote edge service will receive an 'unassign' command to remove rule chain " +
624 EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + ". " + 644 EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + ". " +
625 - "Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally.", 645 + "Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally." + TENANT_AUTHORITY_PARAGRAPH,
626 produces = MediaType.APPLICATION_JSON_VALUE) 646 produces = MediaType.APPLICATION_JSON_VALUE)
627 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 647 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
628 @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) 648 @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.DELETE)
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import io.swagger.annotations.ApiOperation;
  19 +import io.swagger.annotations.ApiParam;
18 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.core.io.ByteArrayResource; 21 import org.springframework.core.io.ByteArrayResource;
20 import org.springframework.http.HttpHeaders; 22 import org.springframework.http.HttpHeaders;
@@ -45,6 +47,22 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -45,6 +47,22 @@ import org.thingsboard.server.service.security.permission.Resource;
45 import java.util.Base64; 47 import java.util.Base64;
46 import java.util.List; 48 import java.util.List;
47 49
  50 +import static org.thingsboard.server.controller.ControllerConstants.LWM2M_OBJECT_DESCRIPTION;
  51 +import static org.thingsboard.server.controller.ControllerConstants.LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES;
  52 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  53 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  54 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  55 +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_DESCRIPTION;
  56 +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_ID_PARAM_DESCRIPTION;
  57 +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_INFO_DESCRIPTION;
  58 +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES;
  59 +import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_TEXT_SEARCH_DESCRIPTION;
  60 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  61 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  62 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  63 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
  64 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
  65 +
48 @Slf4j 66 @Slf4j
49 @RestController 67 @RestController
50 @TbCoreComponent 68 @TbCoreComponent
@@ -53,10 +71,12 @@ public class TbResourceController extends BaseController { @@ -53,10 +71,12 @@ public class TbResourceController extends BaseController {
53 71
54 public static final String RESOURCE_ID = "resourceId"; 72 public static final String RESOURCE_ID = "resourceId";
55 73
  74 + @ApiOperation(value = "Download Resource (downloadResource)", notes = "Download Resource based on the provided Resource Id." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
56 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 75 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
57 @RequestMapping(value = "/resource/{resourceId}/download", method = RequestMethod.GET) 76 @RequestMapping(value = "/resource/{resourceId}/download", method = RequestMethod.GET)
58 @ResponseBody 77 @ResponseBody
59 - public ResponseEntity<org.springframework.core.io.Resource> downloadResource(@PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { 78 + public ResponseEntity<org.springframework.core.io.Resource> downloadResource(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
  79 + @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException {
60 checkParameter(RESOURCE_ID, strResourceId); 80 checkParameter(RESOURCE_ID, strResourceId);
61 try { 81 try {
62 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); 82 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
@@ -74,10 +94,15 @@ public class TbResourceController extends BaseController { @@ -74,10 +94,15 @@ public class TbResourceController extends BaseController {
74 } 94 }
75 } 95 }
76 96
  97 + @ApiOperation(value = "Get Resource Info (getResourceInfoById)",
  98 + notes = "Fetch the Resource Info object based on the provided Resource Id. " +
  99 + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH,
  100 + produces = "application/json")
77 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 101 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
78 @RequestMapping(value = "/resource/info/{resourceId}", method = RequestMethod.GET) 102 @RequestMapping(value = "/resource/info/{resourceId}", method = RequestMethod.GET)
79 @ResponseBody 103 @ResponseBody
80 - public TbResourceInfo getResourceInfoById(@PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { 104 + public TbResourceInfo getResourceInfoById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
  105 + @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException {
81 checkParameter(RESOURCE_ID, strResourceId); 106 checkParameter(RESOURCE_ID, strResourceId);
82 try { 107 try {
83 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); 108 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
@@ -87,10 +112,15 @@ public class TbResourceController extends BaseController { @@ -87,10 +112,15 @@ public class TbResourceController extends BaseController {
87 } 112 }
88 } 113 }
89 114
  115 + @ApiOperation(value = "Get Resource (getResourceById)",
  116 + notes = "Fetch the Resource object based on the provided Resource Id. " +
  117 + RESOURCE_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH,
  118 + produces = "application/json")
90 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 119 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
91 @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.GET) 120 @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.GET)
92 @ResponseBody 121 @ResponseBody
93 - public TbResource getResourceById(@PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { 122 + public TbResource getResourceById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
  123 + @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException {
94 checkParameter(RESOURCE_ID, strResourceId); 124 checkParameter(RESOURCE_ID, strResourceId);
95 try { 125 try {
96 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); 126 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
@@ -100,10 +130,19 @@ public class TbResourceController extends BaseController { @@ -100,10 +130,19 @@ public class TbResourceController extends BaseController {
100 } 130 }
101 } 131 }
102 132
  133 + @ApiOperation(value = "Create Or Update Resource (saveResource)",
  134 + notes = "Create or update the Resource. When creating the Resource, platform generates Resource id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  135 + "The newly created Resource id will be present in the response. " +
  136 + "Specify existing Resource id to update the Resource. " +
  137 + "Referencing non-existing Resource Id will cause 'Not Found' error. " +
  138 + "\n\nResource combination of the title with the key is unique in the scope of tenant. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH,
  139 + produces = "application/json",
  140 + consumes = "application/json")
103 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 141 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
104 @RequestMapping(value = "/resource", method = RequestMethod.POST) 142 @RequestMapping(value = "/resource", method = RequestMethod.POST)
105 @ResponseBody 143 @ResponseBody
106 - public TbResource saveResource(@RequestBody TbResource resource) throws ThingsboardException { 144 + public TbResource saveResource(@ApiParam(value = "A JSON value representing the Resource.")
  145 + @RequestBody TbResource resource) throws ThingsboardException {
107 boolean created = resource.getId() == null; 146 boolean created = resource.getId() == null;
108 try { 147 try {
109 resource.setTenantId(getTenantId()); 148 resource.setTenantId(getTenantId());
@@ -120,13 +159,22 @@ public class TbResourceController extends BaseController { @@ -120,13 +159,22 @@ public class TbResourceController extends BaseController {
120 } 159 }
121 } 160 }
122 161
  162 + @ApiOperation(value = "Get Resource Infos (getResources)",
  163 + notes = "Returns a page of Resource Info objects owned by tenant or sysadmin. " +
  164 + PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH,
  165 + produces = "application/json")
123 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 166 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
124 @RequestMapping(value = "/resource", method = RequestMethod.GET) 167 @RequestMapping(value = "/resource", method = RequestMethod.GET)
125 @ResponseBody 168 @ResponseBody
126 - public PageData<TbResourceInfo> getResources(@RequestParam int pageSize, 169 + public PageData<TbResourceInfo> getResources(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
  170 + @RequestParam int pageSize,
  171 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
127 @RequestParam int page, 172 @RequestParam int page,
  173 + @ApiParam(value = RESOURCE_TEXT_SEARCH_DESCRIPTION)
128 @RequestParam(required = false) String textSearch, 174 @RequestParam(required = false) String textSearch,
  175 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES)
129 @RequestParam(required = false) String sortProperty, 176 @RequestParam(required = false) String sortProperty,
  177 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
130 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 178 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
131 try { 179 try {
132 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); 180 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
@@ -140,13 +188,22 @@ public class TbResourceController extends BaseController { @@ -140,13 +188,22 @@ public class TbResourceController extends BaseController {
140 } 188 }
141 } 189 }
142 190
  191 + @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjectsPage)",
  192 + notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " +
  193 + PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH,
  194 + produces = "application/json")
143 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 195 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
144 @RequestMapping(value = "/resource/lwm2m/page", method = RequestMethod.GET) 196 @RequestMapping(value = "/resource/lwm2m/page", method = RequestMethod.GET)
145 @ResponseBody 197 @ResponseBody
146 - public List<LwM2mObject> getLwm2mListObjectsPage(@RequestParam int pageSize, 198 + public List<LwM2mObject> getLwm2mListObjectsPage(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
  199 + @RequestParam int pageSize,
  200 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
147 @RequestParam int page, 201 @RequestParam int page,
  202 + @ApiParam(value = RESOURCE_TEXT_SEARCH_DESCRIPTION)
148 @RequestParam(required = false) String textSearch, 203 @RequestParam(required = false) String textSearch,
  204 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES)
149 @RequestParam(required = false) String sortProperty, 205 @RequestParam(required = false) String sortProperty,
  206 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
150 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 207 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
151 try { 208 try {
152 PageLink pageLink = new PageLink(pageSize, page, textSearch); 209 PageLink pageLink = new PageLink(pageSize, page, textSearch);
@@ -156,11 +213,18 @@ public class TbResourceController extends BaseController { @@ -156,11 +213,18 @@ public class TbResourceController extends BaseController {
156 } 213 }
157 } 214 }
158 215
  216 + @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)",
  217 + notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " +
  218 + "You can specify parameters to filter the results. " + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH,
  219 + produces = "application/json")
159 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 220 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
160 @RequestMapping(value = "/resource/lwm2m", method = RequestMethod.GET) 221 @RequestMapping(value = "/resource/lwm2m", method = RequestMethod.GET)
161 @ResponseBody 222 @ResponseBody
162 - public List<LwM2mObject> getLwm2mListObjects(@RequestParam String sortOrder, 223 + public List<LwM2mObject> getLwm2mListObjects(@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES, required = true)
  224 + @RequestParam String sortOrder,
  225 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES, required = true)
163 @RequestParam String sortProperty, 226 @RequestParam String sortProperty,
  227 + @ApiParam(value = "LwM2M Object ids.", required = true)
164 @RequestParam(required = false) String[] objectIds) throws ThingsboardException { 228 @RequestParam(required = false) String[] objectIds) throws ThingsboardException {
165 try { 229 try {
166 return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds)); 230 return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds));
@@ -169,10 +233,13 @@ public class TbResourceController extends BaseController { @@ -169,10 +233,13 @@ public class TbResourceController extends BaseController {
169 } 233 }
170 } 234 }
171 235
  236 + @ApiOperation(value = "Delete Resource (deleteResource)",
  237 + notes = "Deletes the Resource. Referencing non-existing Resource Id will cause an error." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
172 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 238 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
173 @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.DELETE) 239 @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.DELETE)
174 @ResponseBody 240 @ResponseBody
175 - public void deleteResource(@PathVariable("resourceId") String strResourceId) throws ThingsboardException { 241 + public void deleteResource(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
  242 + @PathVariable("resourceId") String strResourceId) throws ThingsboardException {
176 checkParameter(RESOURCE_ID, strResourceId); 243 checkParameter(RESOURCE_ID, strResourceId);
177 try { 244 try {
178 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); 245 TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
@@ -103,6 +103,14 @@ import java.util.concurrent.Executors; @@ -103,6 +103,14 @@ import java.util.concurrent.Executors;
103 import java.util.concurrent.TimeUnit; 103 import java.util.concurrent.TimeUnit;
104 import java.util.stream.Collectors; 104 import java.util.stream.Collectors;
105 105
  106 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION;
  107 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION;
  108 +import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_PARAM_DESCRIPTION;
  109 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  110 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  111 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  112 +
  113 +
106 /** 114 /**
107 * Created by ashvayka on 22.03.18. 115 * Created by ashvayka on 22.03.18.
108 */ 116 */
@@ -182,7 +190,8 @@ public class TelemetryController extends BaseController { @@ -182,7 +190,8 @@ public class TelemetryController extends BaseController {
182 @ApiOperation(value = "Get all attribute keys (getAttributeKeys)", 190 @ApiOperation(value = "Get all attribute keys (getAttributeKeys)",
183 notes = "Returns a list of all attribute key names for the selected entity. " + 191 notes = "Returns a list of all attribute key names for the selected entity. " +
184 "In the case of device entity specified, a response will include merged attribute key names list from each scope: " + 192 "In the case of device entity specified, a response will include merged attribute key names list from each scope: " +
185 - "SERVER_SCOPE, CLIENT_SCOPE, SHARED_SCOPE. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 193 + "SERVER_SCOPE, CLIENT_SCOPE, SHARED_SCOPE. "
  194 + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
186 produces = MediaType.APPLICATION_JSON_VALUE) 195 produces = MediaType.APPLICATION_JSON_VALUE)
187 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 196 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
188 @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET) 197 @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET)
@@ -195,7 +204,8 @@ public class TelemetryController extends BaseController { @@ -195,7 +204,8 @@ public class TelemetryController extends BaseController {
195 204
196 @ApiOperation(value = "Get all attributes keys by scope (getAttributeKeysByScope)", 205 @ApiOperation(value = "Get all attributes keys by scope (getAttributeKeysByScope)",
197 notes = "Returns a list of attribute key names from the specified attributes scope for the selected entity. " + 206 notes = "Returns a list of attribute key names from the specified attributes scope for the selected entity. " +
198 - "If scope parameter is omitted, Get all attribute keys(getAttributeKeys) API will be called. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 207 + "If scope parameter is omitted, Get all attribute keys(getAttributeKeys) API will be called. "
  208 + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
199 produces = MediaType.APPLICATION_JSON_VALUE) 209 produces = MediaType.APPLICATION_JSON_VALUE)
200 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 210 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
201 @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET) 211 @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET)
@@ -210,7 +220,7 @@ public class TelemetryController extends BaseController { @@ -210,7 +220,7 @@ public class TelemetryController extends BaseController {
210 220
211 @ApiOperation(value = "Get attributes (getAttributes)", 221 @ApiOperation(value = "Get attributes (getAttributes)",
212 notes = GET_ALL_ATTRIBUTES_BASE_DESCRIPTION + " If 'keys' parameter is omitted, AttributeData class objects will be added to the response for all existing keys of the selected entity. " + 222 notes = GET_ALL_ATTRIBUTES_BASE_DESCRIPTION + " If 'keys' parameter is omitted, AttributeData class objects will be added to the response for all existing keys of the selected entity. " +
213 - INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 223 + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
214 produces = MediaType.APPLICATION_JSON_VALUE) 224 produces = MediaType.APPLICATION_JSON_VALUE)
215 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 225 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
216 @RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET) 226 @RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET)
@@ -228,7 +238,7 @@ public class TelemetryController extends BaseController { @@ -228,7 +238,7 @@ public class TelemetryController extends BaseController {
228 notes = GET_ALL_ATTRIBUTES_BY_SCOPE_BASE_DESCRIPTION + " In case that 'keys' parameter is not selected, " + 238 notes = GET_ALL_ATTRIBUTES_BY_SCOPE_BASE_DESCRIPTION + " In case that 'keys' parameter is not selected, " +
229 "AttributeData class objects will be added to the response for all existing attribute keys from the " + 239 "AttributeData class objects will be added to the response for all existing attribute keys from the " +
230 "specified attributes scope of the selected entity. If 'scope' parameter is omitted, " + 240 "specified attributes scope of the selected entity. If 'scope' parameter is omitted, " +
231 - "Get attributes (getAttributes) API will be called. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 241 + "Get attributes (getAttributes) API will be called. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
232 produces = MediaType.APPLICATION_JSON_VALUE) 242 produces = MediaType.APPLICATION_JSON_VALUE)
233 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 243 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
234 @RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET) 244 @RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET)
@@ -245,7 +255,7 @@ public class TelemetryController extends BaseController { @@ -245,7 +255,7 @@ public class TelemetryController extends BaseController {
245 255
246 @ApiOperation(value = "Get timeseries keys (getTimeseriesKeys)", 256 @ApiOperation(value = "Get timeseries keys (getTimeseriesKeys)",
247 notes = "Returns a list of all telemetry key names for the selected entity based on entity id and entity type specified. " + 257 notes = "Returns a list of all telemetry key names for the selected entity based on entity id and entity type specified. " +
248 - INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 258 + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
249 produces = MediaType.APPLICATION_JSON_VALUE) 259 produces = MediaType.APPLICATION_JSON_VALUE)
250 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 260 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
251 @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET) 261 @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET)
@@ -259,7 +269,8 @@ public class TelemetryController extends BaseController { @@ -259,7 +269,8 @@ public class TelemetryController extends BaseController {
259 269
260 @ApiOperation(value = "Get latest timeseries (getLatestTimeseries)", 270 @ApiOperation(value = "Get latest timeseries (getLatestTimeseries)",
261 notes = "Returns a JSON structure that represents a Map, where the map key is a telemetry key name " + 271 notes = "Returns a JSON structure that represents a Map, where the map key is a telemetry key name " +
262 - "and map value - is a singleton list of TsData class objects. " + TS_DATA_CLASS_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 272 + "and map value - is a singleton list of TsData class objects. "
  273 + + TS_DATA_CLASS_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
263 produces = MediaType.APPLICATION_JSON_VALUE) 274 produces = MediaType.APPLICATION_JSON_VALUE)
264 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 275 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
265 @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET) 276 @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET)
@@ -280,7 +291,8 @@ public class TelemetryController extends BaseController { @@ -280,7 +291,8 @@ public class TelemetryController extends BaseController {
280 "and map value - is a list of TsData class objects. " + TS_DATA_CLASS_DESCRIPTION + 291 "and map value - is a list of TsData class objects. " + TS_DATA_CLASS_DESCRIPTION +
281 "This method allows us to group original data into intervals and aggregate it using one of the aggregation methods or just limit the number of TsData objects to fetch for each key specified. " + 292 "This method allows us to group original data into intervals and aggregate it using one of the aggregation methods or just limit the number of TsData objects to fetch for each key specified. " +
282 "See the desription of the request parameters for more details. " + 293 "See the desription of the request parameters for more details. " +
283 - "The result can also be sorted in ascending or descending order. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 294 + "The result can also be sorted in ascending or descending order. "
  295 + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
284 produces = MediaType.APPLICATION_JSON_VALUE) 296 produces = MediaType.APPLICATION_JSON_VALUE)
285 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 297 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
286 @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET, params = {"keys", "startTs", "endTs"}) 298 @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET, params = {"keys", "startTs", "endTs"})
@@ -321,7 +333,7 @@ public class TelemetryController extends BaseController { @@ -321,7 +333,7 @@ public class TelemetryController extends BaseController {
321 notes = "Creates or updates the device attributes based on device id, specified attribute scope, " + 333 notes = "Creates or updates the device attributes based on device id, specified attribute scope, " +
322 "and request payload that represents a JSON object with key-value format of attributes to create or update. " + 334 "and request payload that represents a JSON object with key-value format of attributes to create or update. " +
323 "For example, '{\"temperature\": 26}'. Key is a unique parameter and cannot be overwritten. Only value can " + 335 "For example, '{\"temperature\": 26}'. Key is a unique parameter and cannot be overwritten. Only value can " +
324 - "be overwritten for the key. ", 336 + "be overwritten for the key. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
325 produces = MediaType.APPLICATION_JSON_VALUE) 337 produces = MediaType.APPLICATION_JSON_VALUE)
326 @ApiResponses(value = { 338 @ApiResponses(value = {
327 @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + 339 @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK +
@@ -344,7 +356,7 @@ public class TelemetryController extends BaseController { @@ -344,7 +356,7 @@ public class TelemetryController extends BaseController {
344 } 356 }
345 357
346 @ApiOperation(value = "Save or update attributes (saveEntityAttributesV1)", 358 @ApiOperation(value = "Save or update attributes (saveEntityAttributesV1)",
347 - notes = SAVE_ENTITY_ATTRIBUTES_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 359 + notes = SAVE_ENTITY_ATTRIBUTES_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
348 produces = MediaType.APPLICATION_JSON_VALUE) 360 produces = MediaType.APPLICATION_JSON_VALUE)
349 @ApiResponses(value = { 361 @ApiResponses(value = {
350 @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), 362 @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK),
@@ -365,7 +377,7 @@ public class TelemetryController extends BaseController { @@ -365,7 +377,7 @@ public class TelemetryController extends BaseController {
365 } 377 }
366 378
367 @ApiOperation(value = "Save or update attributes (saveEntityAttributesV2)", 379 @ApiOperation(value = "Save or update attributes (saveEntityAttributesV2)",
368 - notes = SAVE_ENTITY_ATTRIBUTES_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 380 + notes = SAVE_ENTITY_ATTRIBUTES_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
369 produces = MediaType.APPLICATION_JSON_VALUE) 381 produces = MediaType.APPLICATION_JSON_VALUE)
370 @ApiResponses(value = { 382 @ApiResponses(value = {
371 @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), 383 @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK),
@@ -386,7 +398,7 @@ public class TelemetryController extends BaseController { @@ -386,7 +398,7 @@ public class TelemetryController extends BaseController {
386 } 398 }
387 399
388 @ApiOperation(value = "Save or update telemetry (saveEntityTelemetry)", 400 @ApiOperation(value = "Save or update telemetry (saveEntityTelemetry)",
389 - notes = SAVE_ENTITY_TIMESERIES_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 401 + notes = SAVE_ENTITY_TIMESERIES_DESCRIPTION + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
390 produces = MediaType.APPLICATION_JSON_VALUE) 402 produces = MediaType.APPLICATION_JSON_VALUE)
391 @ApiResponses(value = { 403 @ApiResponses(value = {
392 @ApiResponse(code = 200, message = SAVE_ENTITY_TIMESERIES_STATUS_OK), 404 @ApiResponse(code = 200, message = SAVE_ENTITY_TIMESERIES_STATUS_OK),
@@ -407,7 +419,8 @@ public class TelemetryController extends BaseController { @@ -407,7 +419,8 @@ public class TelemetryController extends BaseController {
407 } 419 }
408 420
409 @ApiOperation(value = "Save or update telemetry with TTL (saveEntityTelemetryWithTTL)", 421 @ApiOperation(value = "Save or update telemetry with TTL (saveEntityTelemetryWithTTL)",
410 - notes = SAVE_ENTITY_TIMESERIES_DESCRIPTION + "The ttl parameter used only in case of Cassandra DB use for timeseries data storage. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 422 + notes = SAVE_ENTITY_TIMESERIES_DESCRIPTION + "The ttl parameter used only in case of Cassandra DB use for timeseries data storage. "
  423 + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
411 produces = MediaType.APPLICATION_JSON_VALUE) 424 produces = MediaType.APPLICATION_JSON_VALUE)
412 @ApiResponses(value = { 425 @ApiResponses(value = {
413 @ApiResponse(code = 200, message = SAVE_ENTITY_TIMESERIES_STATUS_OK), 426 @ApiResponse(code = 200, message = SAVE_ENTITY_TIMESERIES_STATUS_OK),
@@ -431,7 +444,7 @@ public class TelemetryController extends BaseController { @@ -431,7 +444,7 @@ public class TelemetryController extends BaseController {
431 @ApiOperation(value = "Delete entity timeseries (deleteEntityTimeseries)", 444 @ApiOperation(value = "Delete entity timeseries (deleteEntityTimeseries)",
432 notes = "Delete timeseries for selected entity based on entity id, entity type, keys " + 445 notes = "Delete timeseries for selected entity based on entity id, entity type, keys " +
433 "and removal time range. To delete all data for keys parameter 'deleteAllDataForKeys' should be set to true, " + 446 "and removal time range. To delete all data for keys parameter 'deleteAllDataForKeys' should be set to true, " +
434 - "otherwise, will be deleted data that is in range of the selected time interval. ", 447 + "otherwise, will be deleted data that is in range of the selected time interval. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
435 produces = MediaType.APPLICATION_JSON_VALUE) 448 produces = MediaType.APPLICATION_JSON_VALUE)
436 @ApiResponses(value = { 449 @ApiResponses(value = {
437 @ApiResponse(code = 200, message = "Timeseries for the selected keys in the request was removed. " + 450 @ApiResponse(code = 200, message = "Timeseries for the selected keys in the request was removed. " +
@@ -506,7 +519,7 @@ public class TelemetryController extends BaseController { @@ -506,7 +519,7 @@ public class TelemetryController extends BaseController {
506 519
507 @ApiOperation(value = "Delete device attributes (deleteEntityAttributes)", 520 @ApiOperation(value = "Delete device attributes (deleteEntityAttributes)",
508 notes = "Delete device attributes from the specified attributes scope based on device id and a list of keys to delete. " + 521 notes = "Delete device attributes from the specified attributes scope based on device id and a list of keys to delete. " +
509 - "Selected keys will be deleted only if there are exist in the specified attribute scope. Referencing a non-existing device Id will cause an error", 522 + "Selected keys will be deleted only if there are exist in the specified attribute scope. Referencing a non-existing device Id will cause an error" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
510 produces = MediaType.APPLICATION_JSON_VALUE) 523 produces = MediaType.APPLICATION_JSON_VALUE)
511 @ApiResponses(value = { 524 @ApiResponses(value = {
512 @ApiResponse(code = 200, message = "Device attributes was removed for the selected keys in the request. " + 525 @ApiResponse(code = 200, message = "Device attributes was removed for the selected keys in the request. " +
@@ -529,7 +542,7 @@ public class TelemetryController extends BaseController { @@ -529,7 +542,7 @@ public class TelemetryController extends BaseController {
529 542
530 @ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)", 543 @ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)",
531 notes = "Delete entity attributes from the specified attributes scope based on entity id, entity type and a list of keys to delete. " + 544 notes = "Delete entity attributes from the specified attributes scope based on entity id, entity type and a list of keys to delete. " +
532 - "Selected keys will be deleted only if there are exist in the specified attribute scope." + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION, 545 + "Selected keys will be deleted only if there are exist in the specified attribute scope." + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
533 produces = MediaType.APPLICATION_JSON_VALUE) 546 produces = MediaType.APPLICATION_JSON_VALUE)
534 @ApiResponses(value = { 547 @ApiResponses(value = {
535 @ApiResponse(code = 200, message = "Entity attributes was removed for the selected keys in the request. " + 548 @ApiResponse(code = 200, message = "Entity attributes was removed for the selected keys in the request. " +
@@ -43,6 +43,21 @@ import org.thingsboard.server.service.install.InstallScripts; @@ -43,6 +43,21 @@ import org.thingsboard.server.service.install.InstallScripts;
43 import org.thingsboard.server.service.security.permission.Operation; 43 import org.thingsboard.server.service.security.permission.Operation;
44 import org.thingsboard.server.service.security.permission.Resource; 44 import org.thingsboard.server.service.security.permission.Resource;
45 45
  46 +import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD;
  47 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS;
  48 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
  49 +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
  50 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
  51 +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
  52 +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
  53 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
  54 +import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH;
  55 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID;
  56 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION;
  57 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_INFO_SORT_PROPERTY_ALLOWABLE_VALUES;
  58 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_SORT_PROPERTY_ALLOWABLE_VALUES;
  59 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_TEXT_SEARCH_DESCRIPTION;
  60 +
46 @RestController 61 @RestController
47 @TbCoreComponent 62 @TbCoreComponent
48 @RequestMapping("/api") 63 @RequestMapping("/api")
@@ -40,6 +40,8 @@ import org.thingsboard.server.queue.util.TbCoreComponent; @@ -40,6 +40,8 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
40 import org.thingsboard.server.service.security.permission.Operation; 40 import org.thingsboard.server.service.security.permission.Operation;
41 import org.thingsboard.server.service.security.permission.Resource; 41 import org.thingsboard.server.service.security.permission.Resource;
42 42
  43 +import static org.thingsboard.server.controller.ControllerConstants.*;
  44 +
43 @RestController 45 @RestController
44 @TbCoreComponent 46 @TbCoreComponent
45 @RequestMapping("/api") 47 @RequestMapping("/api")
@@ -62,6 +62,8 @@ import org.thingsboard.server.service.security.system.SystemSecurityService; @@ -62,6 +62,8 @@ import org.thingsboard.server.service.security.system.SystemSecurityService;
62 import javax.servlet.http.HttpServletRequest; 62 import javax.servlet.http.HttpServletRequest;
63 import java.util.List; 63 import java.util.List;
64 64
  65 +import static org.thingsboard.server.controller.ControllerConstants.*;
  66 +
65 @RequiredArgsConstructor 67 @RequiredArgsConstructor
66 @RestController 68 @RestController
67 @TbCoreComponent 69 @TbCoreComponent
@@ -302,7 +304,7 @@ public class UserController extends BaseController { @@ -302,7 +304,7 @@ public class UserController extends BaseController {
302 304
303 @ApiOperation(value = "Get Users (getUsers)", 305 @ApiOperation(value = "Get Users (getUsers)",
304 notes = "Returns a page of users owned by tenant or customer. The scope depends on authority of the user that performs the request." + 306 notes = "Returns a page of users owned by tenant or customer. The scope depends on authority of the user that performs the request." +
305 - PAGE_DATA_PARAMETERS + TENANT_OR_USER_AUTHORITY_PARAGRAPH) 307 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
306 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 308 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
307 @RequestMapping(value = "/users", params = {"pageSize", "page"}, method = RequestMethod.GET) 309 @RequestMapping(value = "/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
308 @ResponseBody 310 @ResponseBody
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import io.swagger.annotations.ApiOperation;
  19 +import io.swagger.annotations.ApiParam;
18 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.http.HttpStatus; 21 import org.springframework.http.HttpStatus;
20 import org.springframework.security.access.prepost.PreAuthorize; 22 import org.springframework.security.access.prepost.PreAuthorize;
@@ -26,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestParam; @@ -26,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestParam;
26 import org.springframework.web.bind.annotation.ResponseBody; 28 import org.springframework.web.bind.annotation.ResponseBody;
27 import org.springframework.web.bind.annotation.ResponseStatus; 29 import org.springframework.web.bind.annotation.ResponseStatus;
28 import org.springframework.web.bind.annotation.RestController; 30 import org.springframework.web.bind.annotation.RestController;
29 -import org.thingsboard.server.common.data.EntityType;  
30 import org.thingsboard.server.common.data.edge.EdgeEventActionType; 31 import org.thingsboard.server.common.data.edge.EdgeEventActionType;
31 import org.thingsboard.server.common.data.exception.ThingsboardException; 32 import org.thingsboard.server.common.data.exception.ThingsboardException;
32 import org.thingsboard.server.common.data.id.TenantId; 33 import org.thingsboard.server.common.data.id.TenantId;
@@ -42,16 +43,28 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -42,16 +43,28 @@ import org.thingsboard.server.service.security.permission.Resource;
42 43
43 import java.util.List; 44 import java.util.List;
44 45
  46 +import static org.thingsboard.server.controller.ControllerConstants.*;
  47 +
45 @Slf4j 48 @Slf4j
46 @RestController 49 @RestController
47 @TbCoreComponent 50 @TbCoreComponent
48 @RequestMapping("/api") 51 @RequestMapping("/api")
49 public class WidgetTypeController extends BaseController { 52 public class WidgetTypeController extends BaseController {
50 53
  54 + private static final String WIDGET_TYPE_DESCRIPTION = "Widget Type represents the template for widget creation. Widget Type and Widget are similar to class and object in OOP theory.";
  55 + private static final String WIDGET_TYPE_DETAILS_DESCRIPTION = "Widget Type Details extend Widget Type and add image and description properties. " +
  56 + "Those properties are useful to edit the Widget Type but they are not required for Dashboard rendering. ";
  57 + private static final String WIDGET_TYPE_INFO_DESCRIPTION = "Widget Type Info is a lightweight object that represents Widget Type but does not contain the heavyweight widget descriptor JSON";
  58 +
  59 +
  60 + @ApiOperation(value = "Get Widget Type Details (getWidgetTypeById)",
  61 + notes = "Get the Widget Type Details based on the provided Widget Type Id. " + WIDGET_TYPE_DETAILS_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
51 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 62 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
52 @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET) 63 @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET)
53 @ResponseBody 64 @ResponseBody
54 - public WidgetTypeDetails getWidgetTypeById(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { 65 + public WidgetTypeDetails getWidgetTypeById(
  66 + @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true)
  67 + @PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException {
55 checkParameter("widgetTypeId", strWidgetTypeId); 68 checkParameter("widgetTypeId", strWidgetTypeId);
56 try { 69 try {
57 WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); 70 WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
@@ -61,10 +74,21 @@ public class WidgetTypeController extends BaseController { @@ -61,10 +74,21 @@ public class WidgetTypeController extends BaseController {
61 } 74 }
62 } 75 }
63 76
  77 + @ApiOperation(value = "Create Or Update Widget Type (saveWidgetType)",
  78 + notes = "Create or update the Widget Type. " + WIDGET_TYPE_DESCRIPTION + " " +
  79 + "When creating the Widget Type, platform generates Widget Type Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  80 + "The newly created Widget Type Id will be present in the response. " +
  81 + "Specify existing Widget Type id to update the Widget Type. " +
  82 + "Referencing non-existing Widget Type Id will cause 'Not Found' error." +
  83 + "\n\nWidget Type alias is unique in the scope of Widget Bundle. " +
  84 + "Special Tenant Id '13814000-1dd2-11b2-8080-808080808080' is automatically used if the create request is sent by user with 'SYS_ADMIN' authority."
  85 + + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
64 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 86 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
65 @RequestMapping(value = "/widgetType", method = RequestMethod.POST) 87 @RequestMapping(value = "/widgetType", method = RequestMethod.POST)
66 @ResponseBody 88 @ResponseBody
67 - public WidgetTypeDetails saveWidgetType(@RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException { 89 + public WidgetTypeDetails saveWidgetType(
  90 + @ApiParam(value = "A JSON value representing the Widget Type Details.", required = true)
  91 + @RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException {
68 try { 92 try {
69 if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { 93 if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
70 widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID); 94 widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID);
@@ -84,10 +108,14 @@ public class WidgetTypeController extends BaseController { @@ -84,10 +108,14 @@ public class WidgetTypeController extends BaseController {
84 } 108 }
85 } 109 }
86 110
  111 + @ApiOperation(value = "Delete widget type (deleteWidgetType)",
  112 + notes = "Deletes the Widget Type. Referencing non-existing Widget Type Id will cause an error." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
87 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 113 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
88 @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.DELETE) 114 @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.DELETE)
89 @ResponseStatus(value = HttpStatus.OK) 115 @ResponseStatus(value = HttpStatus.OK)
90 - public void deleteWidgetType(@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { 116 + public void deleteWidgetType(
  117 + @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true)
  118 + @PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException {
91 checkParameter("widgetTypeId", strWidgetTypeId); 119 checkParameter("widgetTypeId", strWidgetTypeId);
92 try { 120 try {
93 WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); 121 WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
@@ -101,11 +129,15 @@ public class WidgetTypeController extends BaseController { @@ -101,11 +129,15 @@ public class WidgetTypeController extends BaseController {
101 } 129 }
102 } 130 }
103 131
  132 + @ApiOperation(value = "Get all Widget types for specified Bundle (getBundleWidgetTypes)",
  133 + notes = "Returns an array of Widget Type objects that belong to specified Widget Bundle." + WIDGET_TYPE_DESCRIPTION + " " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
104 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 134 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
105 @RequestMapping(value = "/widgetTypes", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) 135 @RequestMapping(value = "/widgetTypes", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET)
106 @ResponseBody 136 @ResponseBody
107 public List<WidgetType> getBundleWidgetTypes( 137 public List<WidgetType> getBundleWidgetTypes(
  138 + @ApiParam(value = "System or Tenant", required = true)
108 @RequestParam boolean isSystem, 139 @RequestParam boolean isSystem,
  140 + @ApiParam(value = "Widget Bundle alias", required = true)
109 @RequestParam String bundleAlias) throws ThingsboardException { 141 @RequestParam String bundleAlias) throws ThingsboardException {
110 try { 142 try {
111 TenantId tenantId; 143 TenantId tenantId;
@@ -120,11 +152,15 @@ public class WidgetTypeController extends BaseController { @@ -120,11 +152,15 @@ public class WidgetTypeController extends BaseController {
120 } 152 }
121 } 153 }
122 154
  155 + @ApiOperation(value = "Get all Widget types details for specified Bundle (getBundleWidgetTypes)",
  156 + notes = "Returns an array of Widget Type Details objects that belong to specified Widget Bundle." + WIDGET_TYPE_DETAILS_DESCRIPTION + " " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
123 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 157 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
124 @RequestMapping(value = "/widgetTypesDetails", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) 158 @RequestMapping(value = "/widgetTypesDetails", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET)
125 @ResponseBody 159 @ResponseBody
126 public List<WidgetTypeDetails> getBundleWidgetTypesDetails( 160 public List<WidgetTypeDetails> getBundleWidgetTypesDetails(
  161 + @ApiParam(value = "System or Tenant", required = true)
127 @RequestParam boolean isSystem, 162 @RequestParam boolean isSystem,
  163 + @ApiParam(value = "Widget Bundle alias", required = true)
128 @RequestParam String bundleAlias) throws ThingsboardException { 164 @RequestParam String bundleAlias) throws ThingsboardException {
129 try { 165 try {
130 TenantId tenantId; 166 TenantId tenantId;
@@ -139,11 +175,15 @@ public class WidgetTypeController extends BaseController { @@ -139,11 +175,15 @@ public class WidgetTypeController extends BaseController {
139 } 175 }
140 } 176 }
141 177
  178 + @ApiOperation(value = "Get Widget Type Info objects (getBundleWidgetTypesInfos)",
  179 + notes = "Get the Widget Type Info objects based on the provided parameters. " + WIDGET_TYPE_INFO_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
142 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 180 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
143 @RequestMapping(value = "/widgetTypesInfos", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) 181 @RequestMapping(value = "/widgetTypesInfos", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET)
144 @ResponseBody 182 @ResponseBody
145 public List<WidgetTypeInfo> getBundleWidgetTypesInfos( 183 public List<WidgetTypeInfo> getBundleWidgetTypesInfos(
  184 + @ApiParam(value = "System or Tenant", required = true)
146 @RequestParam boolean isSystem, 185 @RequestParam boolean isSystem,
  186 + @ApiParam(value = "Widget Bundle alias", required = true)
147 @RequestParam String bundleAlias) throws ThingsboardException { 187 @RequestParam String bundleAlias) throws ThingsboardException {
148 try { 188 try {
149 TenantId tenantId; 189 TenantId tenantId;
@@ -158,12 +198,17 @@ public class WidgetTypeController extends BaseController { @@ -158,12 +198,17 @@ public class WidgetTypeController extends BaseController {
158 } 198 }
159 } 199 }
160 200
  201 + @ApiOperation(value = "Get Widget Type (getWidgetType)",
  202 + notes = "Get the Widget Type based on the provided parameters. " + WIDGET_TYPE_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
161 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 203 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
162 @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET) 204 @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET)
163 @ResponseBody 205 @ResponseBody
164 public WidgetType getWidgetType( 206 public WidgetType getWidgetType(
  207 + @ApiParam(value = "System or Tenant", required = true)
165 @RequestParam boolean isSystem, 208 @RequestParam boolean isSystem,
  209 + @ApiParam(value = "Widget Bundle alias", required = true)
166 @RequestParam String bundleAlias, 210 @RequestParam String bundleAlias,
  211 + @ApiParam(value = "Widget Type alias", required = true)
167 @RequestParam String alias) throws ThingsboardException { 212 @RequestParam String alias) throws ThingsboardException {
168 try { 213 try {
169 TenantId tenantId; 214 TenantId tenantId;
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import io.swagger.annotations.ApiOperation;
  19 +import io.swagger.annotations.ApiParam;
18 import org.springframework.http.HttpStatus; 20 import org.springframework.http.HttpStatus;
19 import org.springframework.security.access.prepost.PreAuthorize; 21 import org.springframework.security.access.prepost.PreAuthorize;
20 import org.springframework.web.bind.annotation.PathVariable; 22 import org.springframework.web.bind.annotation.PathVariable;
@@ -39,15 +41,23 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -39,15 +41,23 @@ import org.thingsboard.server.service.security.permission.Resource;
39 41
40 import java.util.List; 42 import java.util.List;
41 43
  44 +import static org.thingsboard.server.controller.ControllerConstants.*;
  45 +
42 @RestController 46 @RestController
43 @TbCoreComponent 47 @TbCoreComponent
44 @RequestMapping("/api") 48 @RequestMapping("/api")
45 public class WidgetsBundleController extends BaseController { 49 public class WidgetsBundleController extends BaseController {
46 50
  51 + private static final String WIDGET_BUNDLE_DESCRIPTION = "Widget Bundle represents a group(bundle) of widgets. Widgets are grouped into bundle by type or use case. ";
  52 +
  53 + @ApiOperation(value = "Get Widget Bundle (getWidgetsBundleById)",
  54 + notes = "Get the Widget Bundle based on the provided Widget Bundle Id. " + WIDGET_BUNDLE_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
47 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 55 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
48 @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.GET) 56 @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.GET)
49 @ResponseBody 57 @ResponseBody
50 - public WidgetsBundle getWidgetsBundleById(@PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { 58 + public WidgetsBundle getWidgetsBundleById(
  59 + @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true)
  60 + @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException {
51 checkParameter("widgetsBundleId", strWidgetsBundleId); 61 checkParameter("widgetsBundleId", strWidgetsBundleId);
52 try { 62 try {
53 WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); 63 WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
@@ -57,10 +67,21 @@ public class WidgetsBundleController extends BaseController { @@ -57,10 +67,21 @@ public class WidgetsBundleController extends BaseController {
57 } 67 }
58 } 68 }
59 69
  70 + @ApiOperation(value = "Create Or Update Widget Bundle (saveWidgetsBundle)",
  71 + notes = "Create or update the Widget Bundle. " + WIDGET_BUNDLE_DESCRIPTION + " " +
  72 + "When creating the bundle, platform generates Widget Bundle Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  73 + "The newly created Widget Bundle Id will be present in the response. " +
  74 + "Specify existing Widget Bundle id to update the Widget Bundle. " +
  75 + "Referencing non-existing Widget Bundle Id will cause 'Not Found' error." +
  76 + "\n\nWidget Bundle alias is unique in the scope of tenant. " +
  77 + "Special Tenant Id '13814000-1dd2-11b2-8080-808080808080' is automatically used if the create bundle request is sent by user with 'SYS_ADMIN' authority."
  78 + + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
60 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 79 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
61 @RequestMapping(value = "/widgetsBundle", method = RequestMethod.POST) 80 @RequestMapping(value = "/widgetsBundle", method = RequestMethod.POST)
62 @ResponseBody 81 @ResponseBody
63 - public WidgetsBundle saveWidgetsBundle(@RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException { 82 + public WidgetsBundle saveWidgetsBundle(
  83 + @ApiParam(value = "A JSON value representing the Widget Bundle.", required = true)
  84 + @RequestBody WidgetsBundle widgetsBundle) throws ThingsboardException {
64 try { 85 try {
65 if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { 86 if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
66 widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID); 87 widgetsBundle.setTenantId(TenantId.SYS_TENANT_ID);
@@ -80,10 +101,14 @@ public class WidgetsBundleController extends BaseController { @@ -80,10 +101,14 @@ public class WidgetsBundleController extends BaseController {
80 } 101 }
81 } 102 }
82 103
  104 + @ApiOperation(value = "Delete widgets bundle (deleteWidgetsBundle)",
  105 + notes = "Deletes the widget bundle. Referencing non-existing Widget Bundle Id will cause an error." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
83 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") 106 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
84 @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.DELETE) 107 @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.DELETE)
85 @ResponseStatus(value = HttpStatus.OK) 108 @ResponseStatus(value = HttpStatus.OK)
86 - public void deleteWidgetsBundle(@PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { 109 + public void deleteWidgetsBundle(
  110 + @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true)
  111 + @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException {
87 checkParameter("widgetsBundleId", strWidgetsBundleId); 112 checkParameter("widgetsBundleId", strWidgetsBundleId);
88 try { 113 try {
89 WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); 114 WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
@@ -97,14 +122,22 @@ public class WidgetsBundleController extends BaseController { @@ -97,14 +122,22 @@ public class WidgetsBundleController extends BaseController {
97 } 122 }
98 } 123 }
99 124
  125 + @ApiOperation(value = "Get Widget Bundles (getWidgetsBundles)",
  126 + notes = "Returns a page of Widget Bundle objects available for current user. " + WIDGET_BUNDLE_DESCRIPTION + " " +
  127 + PAGE_DATA_PARAMETERS + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
100 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 128 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
101 @RequestMapping(value = "/widgetsBundles", params = {"pageSize", "page"}, method = RequestMethod.GET) 129 @RequestMapping(value = "/widgetsBundles", params = {"pageSize", "page"}, method = RequestMethod.GET)
102 @ResponseBody 130 @ResponseBody
103 public PageData<WidgetsBundle> getWidgetsBundles( 131 public PageData<WidgetsBundle> getWidgetsBundles(
  132 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
104 @RequestParam int pageSize, 133 @RequestParam int pageSize,
  134 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
105 @RequestParam int page, 135 @RequestParam int page,
  136 + @ApiParam(value = WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION)
106 @RequestParam(required = false) String textSearch, 137 @RequestParam(required = false) String textSearch,
  138 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES)
107 @RequestParam(required = false) String sortProperty, 139 @RequestParam(required = false) String sortProperty,
  140 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
108 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 141 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
109 try { 142 try {
110 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); 143 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
@@ -119,6 +152,8 @@ public class WidgetsBundleController extends BaseController { @@ -119,6 +152,8 @@ public class WidgetsBundleController extends BaseController {
119 } 152 }
120 } 153 }
121 154
  155 + @ApiOperation(value = "Get all Widget Bundles (getWidgetsBundles)",
  156 + notes = "Returns an array of Widget Bundle objects that are available for current user." + WIDGET_BUNDLE_DESCRIPTION + " " + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
122 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") 157 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
123 @RequestMapping(value = "/widgetsBundles", method = RequestMethod.GET) 158 @RequestMapping(value = "/widgetsBundles", method = RequestMethod.GET)
124 @ResponseBody 159 @ResponseBody
@@ -15,18 +15,22 @@ @@ -15,18 +15,22 @@
15 */ 15 */
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import lombok.EqualsAndHashCode; 21 import lombok.EqualsAndHashCode;
20 import org.thingsboard.server.common.data.id.OtaPackageId; 22 import org.thingsboard.server.common.data.id.OtaPackageId;
21 23
22 import java.nio.ByteBuffer; 24 import java.nio.ByteBuffer;
23 25
  26 +@ApiModel
24 @Data 27 @Data
25 @EqualsAndHashCode(callSuper = true) 28 @EqualsAndHashCode(callSuper = true)
26 public class OtaPackage extends OtaPackageInfo { 29 public class OtaPackage extends OtaPackageInfo {
27 30
28 private static final long serialVersionUID = 3091601761339422546L; 31 private static final long serialVersionUID = 3091601761339422546L;
29 32
  33 + @ApiModelProperty(position = 16, value = "OTA Package data.", readOnly = true)
30 private transient ByteBuffer data; 34 private transient ByteBuffer data;
31 35
32 public OtaPackage() { 36 public OtaPackage() {
@@ -16,15 +16,19 @@ @@ -16,15 +16,19 @@
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
18 import com.fasterxml.jackson.annotation.JsonIgnore; 18 import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import io.swagger.annotations.ApiModel;
  21 +import io.swagger.annotations.ApiModelProperty;
19 import lombok.Data; 22 import lombok.Data;
20 import lombok.EqualsAndHashCode; 23 import lombok.EqualsAndHashCode;
21 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
22 -import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;  
23 -import org.thingsboard.server.common.data.ota.OtaPackageType;  
24 import org.thingsboard.server.common.data.id.DeviceProfileId; 25 import org.thingsboard.server.common.data.id.DeviceProfileId;
25 import org.thingsboard.server.common.data.id.OtaPackageId; 26 import org.thingsboard.server.common.data.id.OtaPackageId;
26 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
  29 +import org.thingsboard.server.common.data.ota.OtaPackageType;
27 30
  31 +@ApiModel
28 @Slf4j 32 @Slf4j
29 @Data 33 @Data
30 @EqualsAndHashCode(callSuper = true) 34 @EqualsAndHashCode(callSuper = true)
@@ -32,21 +36,33 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage @@ -32,21 +36,33 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage
32 36
33 private static final long serialVersionUID = 3168391583570815419L; 37 private static final long serialVersionUID = 3168391583570815419L;
34 38
  39 + @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Tenant Id of the ota package can't be changed.", readOnly = true)
35 private TenantId tenantId; 40 private TenantId tenantId;
  41 + @ApiModelProperty(position = 4, value = "JSON object with Device Profile Id. Device Profile Id of the ota package can't be changed.", readOnly = true)
36 private DeviceProfileId deviceProfileId; 42 private DeviceProfileId deviceProfileId;
  43 + @ApiModelProperty(position = 5, value = "OTA Package type.", example = "FIRMWARE", readOnly = true)
37 private OtaPackageType type; 44 private OtaPackageType type;
  45 + @ApiModelProperty(position = 6, value = "OTA Package title.", example = "fw", readOnly = true)
38 private String title; 46 private String title;
  47 + @ApiModelProperty(position = 7, value = "OTA Package version.", example = "1.0", readOnly = true)
39 private String version; 48 private String version;
  49 + @ApiModelProperty(position = 8, value = "OTA Package tag.", example = "fw_1.0", readOnly = true)
40 private String tag; 50 private String tag;
  51 + @ApiModelProperty(position = 9, value = "OTA Package url.", example = "http://thingsboard.org/fw/1", readOnly = true)
41 private String url; 52 private String url;
  53 + @ApiModelProperty(position = 10, value = "Indicates OTA Package 'has data'. Field is returned from DB ('true' if data exists or url is set). If OTA Package 'has data' is 'false' we can not assign the OTA Package to the Device or Device Profile.", example = "true", readOnly = true)
42 private boolean hasData; 54 private boolean hasData;
  55 + @ApiModelProperty(position = 11, value = "OTA Package file name.", example = "fw_1.0", readOnly = true)
43 private String fileName; 56 private String fileName;
  57 + @ApiModelProperty(position = 12, value = "OTA Package content type.", example = "APPLICATION_OCTET_STREAM", readOnly = true)
44 private String contentType; 58 private String contentType;
  59 + @ApiModelProperty(position = 13, value = "OTA Package checksum algorithm.", example = "CRC32", readOnly = true)
45 private ChecksumAlgorithm checksumAlgorithm; 60 private ChecksumAlgorithm checksumAlgorithm;
  61 + @ApiModelProperty(position = 14, value = "OTA Package checksum.", example = "0xd87f7e0c", readOnly = true)
46 private String checksum; 62 private String checksum;
  63 + @ApiModelProperty(position = 15, value = "OTA Package data size.", example = "8", readOnly = true)
47 private Long dataSize; 64 private Long dataSize;
48 65
49 -  
50 public OtaPackageInfo() { 66 public OtaPackageInfo() {
51 super(); 67 super();
52 } 68 }
@@ -72,6 +88,21 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage @@ -72,6 +88,21 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage
72 this.dataSize = otaPackageInfo.getDataSize(); 88 this.dataSize = otaPackageInfo.getDataSize();
73 } 89 }
74 90
  91 + @ApiModelProperty(position = 1, value = "JSON object with the ota package Id. " +
  92 + "Specify existing ota package Id to update the ota package. " +
  93 + "Referencing non-existing ota package id will cause error. " +
  94 + "Omit this field to create new ota package.")
  95 + @Override
  96 + public OtaPackageId getId() {
  97 + return super.getId();
  98 + }
  99 +
  100 + @ApiModelProperty(position = 2, value = "Timestamp of the ota package creation, in milliseconds", example = "1609459200000", readOnly = true)
  101 + @Override
  102 + public long getCreatedTime() {
  103 + return super.getCreatedTime();
  104 + }
  105 +
75 @Override 106 @Override
76 public String getSearchText() { 107 public String getSearchText() {
77 return title; 108 return title;
@@ -87,4 +118,10 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage @@ -87,4 +118,10 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage
87 public boolean hasUrl() { 118 public boolean hasUrl() {
88 return StringUtils.isNotEmpty(url); 119 return StringUtils.isNotEmpty(url);
89 } 120 }
  121 +
  122 + @ApiModelProperty(position = 17, value = "OTA Package description.", example = "Description for the OTA Package fw_1.0")
  123 + @Override
  124 + public JsonNode getAdditionalInfo() {
  125 + return super.getAdditionalInfo();
  126 + }
90 } 127 }
@@ -15,14 +15,18 @@ @@ -15,14 +15,18 @@
15 */ 15 */
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import lombok.EqualsAndHashCode; 21 import lombok.EqualsAndHashCode;
20 import lombok.NoArgsConstructor; 22 import lombok.NoArgsConstructor;
21 23
  24 +@ApiModel
22 @Data 25 @Data
23 @EqualsAndHashCode(callSuper = true) 26 @EqualsAndHashCode(callSuper = true)
24 @NoArgsConstructor 27 @NoArgsConstructor
25 -public class SaveOtaPackageInfoRequest extends OtaPackageInfo{ 28 +public class SaveOtaPackageInfoRequest extends OtaPackageInfo {
  29 + @ApiModelProperty(position = 16, value = "Indicates OTA Package uses url. Should be 'true' if uses url or 'false' if will be used data.", example = "true", readOnly = true)
26 boolean usesUrl; 30 boolean usesUrl;
27 31
28 public SaveOtaPackageInfoRequest(OtaPackageInfo otaPackageInfo, boolean usesUrl) { 32 public SaveOtaPackageInfoRequest(OtaPackageInfo otaPackageInfo, boolean usesUrl) {
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
  18 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 19 import lombok.Data;
19 import lombok.EqualsAndHashCode; 20 import lombok.EqualsAndHashCode;
20 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
@@ -29,8 +30,10 @@ public class TbResource extends TbResourceInfo { @@ -29,8 +30,10 @@ public class TbResource extends TbResourceInfo {
29 private static final long serialVersionUID = 7379609705527272306L; 30 private static final long serialVersionUID = 7379609705527272306L;
30 31
31 @NoXss 32 @NoXss
  33 + @ApiModelProperty(position = 8, value = "Resource file name.", example = "19.xml", readOnly = true)
32 private String fileName; 34 private String fileName;
33 35
  36 + @ApiModelProperty(position = 9, value = "Resource data.", example = "77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLQpGSUxFIElORk9STUFUSU9OCgpPTUEgUGVybWFuZW50IERvY3VtZW50CiAgIEZpbGU6IE9NQS1TVVAtTHdNMk1fQmluYXJ5QXBwRGF0YUNvbnRhaW5lci1WMV8wXzEtMjAxOTAyMjEtQQogICBUeXBlOiB4bWwKClB1YmxpYyBSZWFjaGFibGUgSW5mb3JtYXRpb24KICAgUGF0aDogaHR0cDovL3d3dy5vcGVubW9iaWxlYWxsaWFuY2Uub3JnL3RlY2gvcHJvZmlsZXMKICAgTmFtZTogTHdNMk1fQmluYXJ5QXBwRGF0YUNvbnRhaW5lci12MV8wXzEueG1sCgpOT1JNQVRJVkUgSU5GT1JNQVRJT04KCiAgSW5mb3JtYXRpb24gYWJvdXQgdGhpcyBmaWxlIGNhbiBiZSBmb3VuZCBpbiB0aGUgbGF0ZXN0IHJldmlzaW9uIG9mCgogIE9NQS1UUy1MV00yTV9CaW5hcnlBcHBEYXRhQ29udGFpbmVyLVYxXzBfMQoKICBUaGlzIGlzIGF2YWlsYWJsZSBhdCBodHRwOi8vd3d3Lm9wZW5tb2JpbGVhbGxpYW5jZS5vcmcvCgogIFNlbmQgY29tbWVudHMgdG8gaHR0cHM6Ly9naXRodWIuY29tL09wZW5Nb2JpbGVBbGxpYW5jZS9PTUFfTHdNMk1fZm9yX0RldmVsb3BlcnMvaXNzdWVzCgpDSEFOR0UgSElTVE9SWQoKMTUwNjIwMTggU3RhdHVzIGNoYW5nZWQgdG8gQXBwcm92ZWQgYnkgRE0sIERvYyBSZWYgIyBPTUEtRE0mU0UtMjAxOC0wMDYxLUlOUF9MV00yTV9BUFBEQVRBX1YxXzBfRVJQX2Zvcl9maW5hbF9BcHByb3ZhbAoyMTAyMjAxOSBTdGF0dXMgY2hhbmdlZCB0byBBcHByb3ZlZCBieSBJUFNPLCBEb2MgUmVmICMgT01BLUlQU08tMjAxOS0wMDI1LUlOUF9Md00yTV9PYmplY3RfQXBwX0RhdGFfQ29udGFpbmVyXzFfMF8xX2Zvcl9GaW5hbF9BcHByb3ZhbAoKTEVHQUwgRElTQ0xBSU1FUgoKQ29weXJpZ2h0IDIwMTkgT3BlbiBNb2JpbGUgQWxsaWFuY2UuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCmFyZSBtZXQ6CgoxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodApub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCjIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0Cm5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUKZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cwpjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgoKVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUwoiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUwpGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRQpDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULApJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLApCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7CkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIKQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUCkxJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOCkFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRQpQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KClRoZSBhYm92ZSBsaWNlbnNlIGlzIHVzZWQgYXMgYSBsaWNlbnNlIHVuZGVyIGNvcHlyaWdodCBvbmx5LiBQbGVhc2UKcmVmZXJlbmNlIHRoZSBPTUEgSVBSIFBvbGljeSBmb3IgcGF0ZW50IGxpY2Vuc2luZyB0ZXJtczoKaHR0cHM6Ly93d3cub21hc3BlY3dvcmtzLm9yZy9hYm91dC9pbnRlbGxlY3R1YWwtcHJvcGVydHktcmlnaHRzLwoKLS0+CjxMV00yTSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6bm9OYW1lc3BhY2VTY2hlbWFMb2NhdGlvbj0iaHR0cDovL29wZW5tb2JpbGVhbGxpYW5jZS5vcmcvdGVjaC9wcm9maWxlcy9MV00yTS54c2QiPgoJPE9iamVjdCBPYmplY3RUeXBlPSJNT0RlZmluaXRpb24iPgoJCTxOYW1lPkJpbmFyeUFwcERhdGFDb250YWluZXI8L05hbWU+CgkJPERlc2NyaXB0aW9uMT48IVtDREFUQVtUaGlzIEx3TTJNIE9iamVjdHMgcHJvdmlkZXMgdGhlIGFwcGxpY2F0aW9uIHNlcnZpY2UgZGF0YSByZWxhdGVkIHRvIGEgTHdNMk0gU2VydmVyLCBlZy4gV2F0ZXIgbWV0ZXIgZGF0YS4gClRoZXJlIGFyZSBzZXZlcmFsIG1ldGhvZHMgdG8gY3JlYXRlIGluc3RhbmNlIHRvIGluZGljYXRlIHRoZSBtZXNzYWdlIGRpcmVjdGlvbiBiYXNlZCBvbiB0aGUgbmVnb3RpYXRpb24gYmV0d2VlbiBBcHBsaWNhdGlvbiBhbmQgTHdNMk0uIFRoZSBDbGllbnQgYW5kIFNlcnZlciBzaG91bGQgbmVnb3RpYXRlIHRoZSBpbnN0YW5jZShzKSB1c2VkIHRvIGV4Y2hhbmdlIHRoZSBkYXRhLiBGb3IgZXhhbXBsZToKIC0gVXNpbmcgYSBzaW5nbGUgaW5zdGFuY2UgZm9yIGJvdGggZGlyZWN0aW9ucyBjb21tdW5pY2F0aW9uLCBmcm9tIENsaWVudCB0byBTZXJ2ZXIgYW5kIGZyb20gU2VydmVyIHRvIENsaWVudC4KIC0gVXNpbmcgYW4gaW5zdGFuY2UgZm9yIGNvbW11bmljYXRpb24gZnJvbSBDbGllbnQgdG8gU2VydmVyIGFuZCBhbm90aGVyIG9uZSBmb3IgY29tbXVuaWNhdGlvbiBmcm9tIFNlcnZlciB0byBDbGllbnQKIC0gVXNpbmcgc2V2ZXJhbCBpbnN0YW5jZXMKXV0+PC9EZXNjcmlwdGlvbjE+CgkJPE9iamVjdElEPjE5PC9PYmplY3RJRD4KCQk8T2JqZWN0VVJOPnVybjpvbWE6bHdtMm06b21hOjE5PC9PYmplY3RVUk4+CgkJPExXTTJNVmVyc2lvbj4xLjA8L0xXTTJNVmVyc2lvbj4KCQk8T2JqZWN0VmVyc2lvbj4xLjA8L09iamVjdFZlcnNpb24+CgkJPE11bHRpcGxlSW5zdGFuY2VzPk11bHRpcGxlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQk8TWFuZGF0b3J5Pk9wdGlvbmFsPC9NYW5kYXRvcnk+CgkJPFJlc291cmNlcz4KCQkJPEl0ZW0gSUQ9IjAiPjxOYW1lPkRhdGE8L05hbWU+CgkJCQk8T3BlcmF0aW9ucz5SVzwvT3BlcmF0aW9ucz4KCQkJCTxNdWx0aXBsZUluc3RhbmNlcz5NdWx0aXBsZTwvTXVsdGlwbGVJbnN0YW5jZXM+CgkJCQk8TWFuZGF0b3J5Pk1hbmRhdG9yeTwvTWFuZGF0b3J5PgoJCQkJPFR5cGU+T3BhcXVlPC9UeXBlPgoJCQkJPFJhbmdlRW51bWVyYXRpb24gLz4KCQkJCTxVbml0cyAvPgoJCQkJPERlc2NyaXB0aW9uPjwhW0NEQVRBW0luZGljYXRlcyB0aGUgYXBwbGljYXRpb24gZGF0YSBjb250ZW50Ll1dPjwvRGVzY3JpcHRpb24+CgkJCTwvSXRlbT4KCQkJPEl0ZW0gSUQ9IjEiPjxOYW1lPkRhdGEgUHJpb3JpdHk8L05hbWU+CgkJCQk8T3BlcmF0aW9ucz5SVzwvT3BlcmF0aW9ucz4KCQkJCTxNdWx0aXBsZUluc3RhbmNlcz5TaW5nbGU8L011bHRpcGxlSW5zdGFuY2VzPgoJCQkJPE1hbmRhdG9yeT5PcHRpb25hbDwvTWFuZGF0b3J5PgoJCQkJPFR5cGU+SW50ZWdlcjwvVHlwZT4KCQkJCTxSYW5nZUVudW1lcmF0aW9uPjEgYnl0ZXM8L1JhbmdlRW51bWVyYXRpb24+CgkJCQk8VW5pdHMgLz4KCQkJCTxEZXNjcmlwdGlvbj48IVtDREFUQVtJbmRpY2F0ZXMgdGhlIEFwcGxpY2F0aW9uIGRhdGEgcHJpb3JpdHk6CjA6SW1tZWRpYXRlCjE6QmVzdEVmZm9ydAoyOkxhdGVzdAozLTEwMDogUmVzZXJ2ZWQgZm9yIGZ1dHVyZSB1c2UuCjEwMS0yNTQ6IFByb3ByaWV0YXJ5IG1vZGUuXV0+PC9EZXNjcmlwdGlvbj4KCQkJPC9JdGVtPgoJCQk8SXRlbSBJRD0iMiI+PE5hbWU+RGF0YSBDcmVhdGlvbiBUaW1lPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPlRpbWU8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbiAvPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBEYXRhIGluc3RhbmNlIGNyZWF0aW9uIHRpbWVzdGFtcC5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+CgkJCTxJdGVtIElEPSIzIj48TmFtZT5EYXRhIERlc2NyaXB0aW9uPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPlN0cmluZzwvVHlwZT4KCQkJCTxSYW5nZUVudW1lcmF0aW9uPjMyIGJ5dGVzPC9SYW5nZUVudW1lcmF0aW9uPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBkYXRhIGRlc2NyaXB0aW9uLgplLmcuICJtZXRlciByZWFkaW5nIi5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+CgkJCTxJdGVtIElEPSI0Ij48TmFtZT5EYXRhIEZvcm1hdDwvTmFtZT4KCQkJCTxPcGVyYXRpb25zPlJXPC9PcGVyYXRpb25zPgoJCQkJPE11bHRpcGxlSW5zdGFuY2VzPlNpbmdsZTwvTXVsdGlwbGVJbnN0YW5jZXM+CgkJCQk8TWFuZGF0b3J5Pk9wdGlvbmFsPC9NYW5kYXRvcnk+CgkJCQk8VHlwZT5TdHJpbmc8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbj4zMiBieXRlczwvUmFuZ2VFbnVtZXJhdGlvbj4KCQkJCTxVbml0cyAvPgoJCQkJPERlc2NyaXB0aW9uPjwhW0NEQVRBW0luZGljYXRlcyB0aGUgZm9ybWF0IG9mIHRoZSBBcHBsaWNhdGlvbiBEYXRhLgplLmcuIFlHLU1ldGVyLVdhdGVyLVJlYWRpbmcKVVRGOC1zdHJpbmcKXV0+PC9EZXNjcmlwdGlvbj4KCQkJPC9JdGVtPgoJCQk8SXRlbSBJRD0iNSI+PE5hbWU+QXBwIElEPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPkludGVnZXI8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbj4yIGJ5dGVzPC9SYW5nZUVudW1lcmF0aW9uPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBkZXN0aW5hdGlvbiBBcHBsaWNhdGlvbiBJRC5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+PC9SZXNvdXJjZXM+CgkJPERlc2NyaXB0aW9uMj48IVtDREFUQVtdXT48L0Rlc2NyaXB0aW9uMj4KCTwvT2JqZWN0Pgo8L0xXTTJNPgo=", readOnly = true)
34 private String data; 37 private String data;
35 38
36 public TbResource() { 39 public TbResource() {
@@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
18 import com.fasterxml.jackson.annotation.JsonIgnore; 18 import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import io.swagger.annotations.ApiModel;
  20 +import io.swagger.annotations.ApiModelProperty;
19 import lombok.Data; 21 import lombok.Data;
20 import lombok.EqualsAndHashCode; 22 import lombok.EqualsAndHashCode;
21 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
@@ -23,6 +25,7 @@ import org.thingsboard.server.common.data.id.TbResourceId; @@ -23,6 +25,7 @@ import org.thingsboard.server.common.data.id.TbResourceId;
23 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.common.data.validation.NoXss; 26 import org.thingsboard.server.common.data.validation.NoXss;
25 27
  28 +@ApiModel
26 @Slf4j 29 @Slf4j
27 @Data 30 @Data
28 @EqualsAndHashCode(callSuper = true) 31 @EqualsAndHashCode(callSuper = true)
@@ -30,11 +33,16 @@ public class TbResourceInfo extends SearchTextBased<TbResourceId> implements Has @@ -30,11 +33,16 @@ public class TbResourceInfo extends SearchTextBased<TbResourceId> implements Has
30 33
31 private static final long serialVersionUID = 7282664529021651736L; 34 private static final long serialVersionUID = 7282664529021651736L;
32 35
  36 + @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Tenant Id of the resource can't be changed.", readOnly = true)
33 private TenantId tenantId; 37 private TenantId tenantId;
34 @NoXss 38 @NoXss
  39 + @ApiModelProperty(position = 4, value = "Resource title.", example = "BinaryAppDataContainer id=19 v1.0")
35 private String title; 40 private String title;
  41 + @ApiModelProperty(position = 5, value = "Resource type.", example = "LWM2M_MODEL", readOnly = true)
36 private ResourceType resourceType; 42 private ResourceType resourceType;
  43 + @ApiModelProperty(position = 6, value = "Resource key.", example = "19_1.0", readOnly = true)
37 private String resourceKey; 44 private String resourceKey;
  45 + @ApiModelProperty(position = 7, value = "Resource search text.", example = "19_1.0:binaryappdatacontainer", readOnly = true)
38 private String searchText; 46 private String searchText;
39 47
40 public TbResourceInfo() { 48 public TbResourceInfo() {
@@ -54,6 +62,21 @@ public class TbResourceInfo extends SearchTextBased<TbResourceId> implements Has @@ -54,6 +62,21 @@ public class TbResourceInfo extends SearchTextBased<TbResourceId> implements Has
54 this.searchText = resourceInfo.getSearchText(); 62 this.searchText = resourceInfo.getSearchText();
55 } 63 }
56 64
  65 + @ApiModelProperty(position = 1, value = "JSON object with the Resource Id. " +
  66 + "Specify this field to update the Resource. " +
  67 + "Referencing non-existing Resource Id will cause error. " +
  68 + "Omit this field to create new Resource." )
  69 + @Override
  70 + public TbResourceId getId() {
  71 + return super.getId();
  72 + }
  73 +
  74 + @ApiModelProperty(position = 2, value = "Timestamp of the resource creation, in milliseconds", example = "1609459200000", readOnly = true)
  75 + @Override
  76 + public long getCreatedTime() {
  77 + return super.getCreatedTime();
  78 + }
  79 +
57 @Override 80 @Override
58 @JsonIgnore 81 @JsonIgnore
59 public String getName() { 82 public String getName() {
@@ -69,8 +69,8 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, Ha @@ -69,8 +69,8 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, Ha
69 @ApiModelProperty(position = 15, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") 69 @ApiModelProperty(position = 15, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true")
70 private boolean propagate; 70 private boolean propagate;
71 @ApiModelProperty(position = 16, value = "JSON array of relation types that should be used for propagation. " + 71 @ApiModelProperty(position = 16, value = "JSON array of relation types that should be used for propagation. " +
72 - "By default, 'propagateRelationTypes' array is empty which means that the alarm will propagate based on any relation type to parent entities. " +  
73 - "This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will ignoned.") 72 + "By default, 'propagateRelationTypes' array is empty which means that the alarm will be propagated based on any relation type to parent entities. " +
  73 + "This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will be ignored.")
74 private List<String> propagateRelationTypes; 74 private List<String> propagateRelationTypes;
75 75
76 public Alarm() { 76 public Alarm() {
@@ -16,13 +16,16 @@ @@ -16,13 +16,16 @@
16 package org.thingsboard.server.common.data.device.data; 16 package org.thingsboard.server.common.data.device.data;
17 17
18 import io.swagger.annotations.ApiModel; 18 import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
19 import lombok.Data; 20 import lombok.Data;
20 21
21 @ApiModel 22 @ApiModel
22 @Data 23 @Data
23 public class DeviceData { 24 public class DeviceData {
24 25
  26 + @ApiModelProperty(position = 1, value = "Device configuration for device profile type. DEFAULT is only supported value for now")
25 private DeviceConfiguration configuration; 27 private DeviceConfiguration configuration;
  28 + @ApiModelProperty(position = 2, value = "Device transport configuration used to connect the device")
26 private DeviceTransportConfiguration transportConfiguration; 29 private DeviceTransportConfiguration transportConfiguration;
27 30
28 } 31 }
@@ -16,18 +16,23 @@ @@ -16,18 +16,23 @@
16 package org.thingsboard.server.common.data.device.profile; 16 package org.thingsboard.server.common.data.device.profile;
17 17
18 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 18 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  19 +import io.swagger.annotations.ApiModel;
  20 +import io.swagger.annotations.ApiModelProperty;
19 import lombok.Data; 21 import lombok.Data;
20 22
21 import java.io.Serializable; 23 import java.io.Serializable;
22 import javax.validation.Valid; 24 import javax.validation.Valid;
23 import java.util.List; 25 import java.util.List;
24 26
  27 +@ApiModel
25 @Data 28 @Data
26 @JsonIgnoreProperties(ignoreUnknown = true) 29 @JsonIgnoreProperties(ignoreUnknown = true)
27 public class AlarmCondition implements Serializable { 30 public class AlarmCondition implements Serializable {
28 31
29 @Valid 32 @Valid
  33 + @ApiModelProperty(position = 1, value = "JSON array of alarm condition filters")
30 private List<AlarmConditionFilter> condition; 34 private List<AlarmConditionFilter> condition;
  35 + @ApiModelProperty(position = 2, value = "JSON object representing alarm condition type")
31 private AlarmConditionSpec spec; 36 private AlarmConditionSpec spec;
32 37
33 } 38 }
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.device.profile; 16 package org.thingsboard.server.common.data.device.profile;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import org.thingsboard.server.common.data.query.EntityKeyValueType; 21 import org.thingsboard.server.common.data.query.EntityKeyValueType;
20 import org.thingsboard.server.common.data.query.KeyFilterPredicate; 22 import org.thingsboard.server.common.data.query.KeyFilterPredicate;
@@ -24,15 +26,20 @@ import javax.validation.Valid; @@ -24,15 +26,20 @@ import javax.validation.Valid;
24 26
25 import java.io.Serializable; 27 import java.io.Serializable;
26 28
  29 +@ApiModel
27 @Data 30 @Data
28 public class AlarmConditionFilter implements Serializable { 31 public class AlarmConditionFilter implements Serializable {
29 32
30 @Valid 33 @Valid
  34 + @ApiModelProperty(position = 1, value = "JSON object for specifying alarm condition by specific key")
31 private AlarmConditionFilterKey key; 35 private AlarmConditionFilterKey key;
  36 + @ApiModelProperty(position = 2, value = "String representation of the type of the value", example = "NUMERIC")
32 private EntityKeyValueType valueType; 37 private EntityKeyValueType valueType;
33 @NoXss 38 @NoXss
  39 + @ApiModelProperty(position = 3, value = "Value used in Constant comparison. For other types, such as TIME_SERIES or ATTRIBUTE, the predicate condition is used")
34 private Object value; 40 private Object value;
35 @Valid 41 @Valid
  42 + @ApiModelProperty(position = 4, value = "JSON object representing filter condition")
36 private KeyFilterPredicate predicate; 43 private KeyFilterPredicate predicate;
37 44
38 } 45 }
@@ -15,16 +15,21 @@ @@ -15,16 +15,21 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.device.profile; 16 package org.thingsboard.server.common.data.device.profile;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import org.thingsboard.server.common.data.validation.NoXss; 21 import org.thingsboard.server.common.data.validation.NoXss;
20 22
21 import java.io.Serializable; 23 import java.io.Serializable;
22 24
  25 +@ApiModel
23 @Data 26 @Data
24 public class AlarmConditionFilterKey implements Serializable { 27 public class AlarmConditionFilterKey implements Serializable {
25 28
  29 + @ApiModelProperty(position = 1, value = "The key type", example = "TIME_SERIES")
26 private final AlarmConditionKeyType type; 30 private final AlarmConditionKeyType type;
27 @NoXss 31 @NoXss
  32 + @ApiModelProperty(position = 2, value = "String value representing the key", example = "temp")
28 private final String key; 33 private final String key;
29 34
30 } 35 }
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.device.profile; 16 package org.thingsboard.server.common.data.device.profile;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import org.thingsboard.server.common.data.id.DashboardId; 21 import org.thingsboard.server.common.data.id.DashboardId;
20 import org.thingsboard.server.common.data.validation.NoXss; 22 import org.thingsboard.server.common.data.validation.NoXss;
@@ -23,15 +25,20 @@ import javax.validation.Valid; @@ -23,15 +25,20 @@ import javax.validation.Valid;
23 25
24 import java.io.Serializable; 26 import java.io.Serializable;
25 27
  28 +@ApiModel
26 @Data 29 @Data
27 public class AlarmRule implements Serializable { 30 public class AlarmRule implements Serializable {
28 31
29 @Valid 32 @Valid
  33 + @ApiModelProperty(position = 1, value = "JSON object representing the alarm rule condition")
30 private AlarmCondition condition; 34 private AlarmCondition condition;
  35 + @ApiModelProperty(position = 2, value = "JSON object representing time interval during which the rule is active")
31 private AlarmSchedule schedule; 36 private AlarmSchedule schedule;
32 // Advanced 37 // Advanced
33 @NoXss 38 @NoXss
  39 + @ApiModelProperty(position = 3, value = "String value representing the additional details for an alarm rule")
34 private String alarmDetails; 40 private String alarmDetails;
  41 + @ApiModelProperty(position = 4, value = "JSON object with the dashboard Id representing the reference to alarm details dashboard used by mobile application")
35 private DashboardId dashboardId; 42 private DashboardId dashboardId;
36 43
37 } 44 }