Browse Source

Merge branch 'develop/3.5' into improvements/notification-system

pull/8334/head
ViacheslavKlimov 4 years ago
parent
commit
25e1d73ca0
  1. 2
      application/src/main/data/json/system/widget_bundles/alarm_widgets.json
  2. 178
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  3. 30
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  4. 229
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  5. 38
      application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java
  6. 56
      application/src/main/java/org/thingsboard/server/controller/AuditLogController.java
  7. 164
      application/src/main/java/org/thingsboard/server/controller/AuthController.java
  8. 24
      application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java
  9. 58
      application/src/main/java/org/thingsboard/server/controller/CustomerController.java
  10. 240
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  11. 225
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  12. 50
      application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java
  13. 249
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  14. 14
      application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java
  15. 83
      application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java
  16. 185
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  17. 10
      application/src/main/java/org/thingsboard/server/controller/EventController.java
  18. 6
      application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java
  19. 26
      application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.java
  20. 56
      application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java
  21. 62
      application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java
  22. 100
      application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java
  23. 265
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
  24. 66
      application/src/main/java/org/thingsboard/server/controller/TbResourceController.java
  25. 128
      application/src/main/java/org/thingsboard/server/controller/TelemetryController.java
  26. 38
      application/src/main/java/org/thingsboard/server/controller/TenantController.java
  27. 82
      application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java
  28. 211
      application/src/main/java/org/thingsboard/server/controller/UserController.java
  29. 145
      application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java
  30. 38
      application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java
  31. 9
      application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
  32. 9
      application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java
  33. 23
      application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
  34. 22
      application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java
  35. 18
      application/src/test/java/org/thingsboard/server/controller/BaseEntityQueryControllerTest.java
  36. 30
      application/src/test/java/org/thingsboard/server/controller/BaseHomePageApiTest.java
  37. 99
      application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java
  38. 21
      application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/attributes/updates/MqttAttributesUpdatesIntegrationTest.java
  39. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java
  40. 3
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/MqttDeviceProfileTransportConfiguration.java
  41. 2
      common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java
  42. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcDownlinkRequestCallbackProxy.java
  43. 1
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java
  44. 7
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java
  45. 14
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java
  46. 2
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java
  47. 9
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java
  48. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
  49. 8
      dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
  50. 11
      dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java
  51. 9
      dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java
  52. 14
      rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java
  53. 16
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java
  54. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java
  55. 6
      ui-ngx/src/app/core/http/user.service.ts
  56. 3
      ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.html
  57. 12
      ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.scss
  58. 14
      ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.ts
  59. 35
      ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.html
  60. 55
      ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss
  61. 92
      ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts
  62. 17
      ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.html
  63. 4
      ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.ts
  64. 247
      ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.html
  65. 157
      ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.scss
  66. 50
      ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.ts
  67. 72
      ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.html
  68. 1
      ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.scss
  69. 40
      ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts
  70. 17
      ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts
  71. 66
      ui-ngx/src/app/modules/home/components/alarm/alarm-table.component.scss
  72. 5
      ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts
  73. 30
      ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts
  74. 15
      ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html
  75. 1
      ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts
  76. 26
      ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts
  77. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html
  78. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts
  79. 2
      ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts
  80. 4
      ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts
  81. 8
      ui-ngx/src/assets/help/en_US/widget/action/custom_additional_params.md
  82. 6
      ui-ngx/src/assets/locale/locale.constant-cs_CZ.json
  83. 24
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  84. 6
      ui-ngx/src/assets/locale/locale.constant-es_ES.json
  85. 6
      ui-ngx/src/assets/locale/locale.constant-fr_FR.json
  86. 6
      ui-ngx/src/assets/locale/locale.constant-ko_KR.json
  87. 6
      ui-ngx/src/assets/locale/locale.constant-sl_SI.json
  88. 6
      ui-ngx/src/assets/locale/locale.constant-tr_TR.json

2
application/src/main/data/json/system/widget_bundles/alarm_widgets.json

@ -23,7 +23,7 @@
"dataKeySettingsSchema": "", "dataKeySettingsSchema": "",
"settingsDirective": "tb-alarms-table-widget-settings", "settingsDirective": "tb-alarms-table-widget-settings",
"dataKeySettingsDirective": "tb-alarms-table-key-settings", "dataKeySettingsDirective": "tb-alarms-table-key-settings",
"defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"allowAssign\":true,\"displayComments\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStickyAction\":false,\"enableFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418},{\"name\":\"assignee\",\"type\":\"alarm\",\"label\":\"Assignee\",\"color\":\"#9c27b0\",\"settings\":{},\"_hash\":0.5008441077416634}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{},\"alarmStatusList\":[],\"alarmSeverityList\":[],\"alarmTypeList\":[],\"searchPropagatedAlarms\":false}" "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"allowAssign\":true,\"displayActivity\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStickyAction\":false,\"enableFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418},{\"name\":\"assignee\",\"type\":\"alarm\",\"label\":\"Assignee\",\"color\":\"#9c27b0\",\"settings\":{},\"_hash\":0.5008441077416634}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{},\"alarmStatusList\":[],\"alarmSeverityList\":[],\"alarmTypeList\":[],\"searchPropagatedAlarms\":false}"
} }
} }
] ]

178
application/src/main/java/org/thingsboard/server/controller/AdminController.java

@ -96,16 +96,12 @@ public class AdminController extends BaseController {
public AdminSettings getAdminSettings( public AdminSettings getAdminSettings(
@ApiParam(value = "A string value of the key (e.g. 'general' or 'mail').") @ApiParam(value = "A string value of the key (e.g. 'general' or 'mail').")
@PathVariable("key") String key) throws ThingsboardException { @PathVariable("key") String key) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key), "No Administration settings found for key: " + key);
AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key), "No Administration settings found for key: " + key); if (adminSettings.getKey().equals("mail")) {
if (adminSettings.getKey().equals("mail")) { ((ObjectNode) adminSettings.getJsonValue()).remove("password");
((ObjectNode) adminSettings.getJsonValue()).remove("password");
}
return adminSettings;
} catch (Exception e) {
throw handleException(e);
} }
return adminSettings;
} }
@ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)", @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)",
@ -118,20 +114,16 @@ public class AdminController extends BaseController {
public AdminSettings saveAdminSettings( public AdminSettings saveAdminSettings(
@ApiParam(value = "A JSON value representing the Administration Settings.") @ApiParam(value = "A JSON value representing the Administration Settings.")
@RequestBody AdminSettings adminSettings) throws ThingsboardException { @RequestBody AdminSettings adminSettings) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); adminSettings.setTenantId(getTenantId());
adminSettings.setTenantId(getTenantId()); adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings)); if (adminSettings.getKey().equals("mail")) {
if (adminSettings.getKey().equals("mail")) { mailService.updateMailConfiguration();
mailService.updateMailConfiguration(); ((ObjectNode) adminSettings.getJsonValue()).remove("password");
((ObjectNode) adminSettings.getJsonValue()).remove("password"); } else if (adminSettings.getKey().equals("sms")) {
} else if (adminSettings.getKey().equals("sms")) { smsService.updateSmsConfiguration();
smsService.updateSmsConfiguration();
}
return adminSettings;
} catch (Exception e) {
throw handleException(e);
} }
return adminSettings;
} }
@ApiOperation(value = "Get the Security Settings object", @ApiOperation(value = "Get the Security Settings object",
@ -140,12 +132,8 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/securitySettings", method = RequestMethod.GET) @RequestMapping(value = "/securitySettings", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public SecuritySettings getSecuritySettings() throws ThingsboardException { public SecuritySettings getSecuritySettings() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); return checkNotNull(systemSecurityService.getSecuritySettings(TenantId.SYS_TENANT_ID));
return checkNotNull(systemSecurityService.getSecuritySettings(TenantId.SYS_TENANT_ID));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Update Security Settings (saveSecuritySettings)", @ApiOperation(value = "Update Security Settings (saveSecuritySettings)",
@ -156,13 +144,9 @@ public class AdminController extends BaseController {
public SecuritySettings saveSecuritySettings( public SecuritySettings saveSecuritySettings(
@ApiParam(value = "A JSON value representing the Security Settings.") @ApiParam(value = "A JSON value representing the Security Settings.")
@RequestBody SecuritySettings securitySettings) throws ThingsboardException { @RequestBody SecuritySettings securitySettings) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(TenantId.SYS_TENANT_ID, securitySettings));
securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(TenantId.SYS_TENANT_ID, securitySettings)); return securitySettings;
return securitySettings;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get the JWT Settings object (getJwtSettings)", @ApiOperation(value = "Get the JWT Settings object (getJwtSettings)",
@ -172,12 +156,8 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/jwtSettings", method = RequestMethod.GET) @RequestMapping(value = "/jwtSettings", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public JwtSettings getJwtSettings() throws ThingsboardException { public JwtSettings getJwtSettings() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); return checkNotNull(jwtSettingsService.getJwtSettings());
return checkNotNull(jwtSettingsService.getJwtSettings());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Update JWT Settings (saveJwtSettings)", @ApiOperation(value = "Update JWT Settings (saveJwtSettings)",
@ -189,14 +169,10 @@ public class AdminController extends BaseController {
public JwtPair saveJwtSettings( public JwtPair saveJwtSettings(
@ApiParam(value = "A JSON value representing the JWT Settings.") @ApiParam(value = "A JSON value representing the JWT Settings.")
@RequestBody JwtSettings jwtSettings) throws ThingsboardException { @RequestBody JwtSettings jwtSettings) throws ThingsboardException {
try { SecurityUser securityUser = getCurrentUser();
SecurityUser securityUser = getCurrentUser(); accessControlService.checkPermission(securityUser, Resource.ADMIN_SETTINGS, Operation.WRITE);
accessControlService.checkPermission(securityUser, Resource.ADMIN_SETTINGS, Operation.WRITE); checkNotNull(jwtSettingsService.saveJwtSettings(jwtSettings));
checkNotNull(jwtSettingsService.saveJwtSettings(jwtSettings)); return tokenFactory.createTokenPair(securityUser);
return tokenFactory.createTokenPair(securityUser);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Send test email (sendTestMail)", @ApiOperation(value = "Send test email (sendTestMail)",
@ -207,19 +183,15 @@ public class AdminController extends BaseController {
public void sendTestMail( public void sendTestMail(
@ApiParam(value = "A JSON value representing the Mail Settings.") @ApiParam(value = "A JSON value representing the Mail Settings.")
@RequestBody AdminSettings adminSettings) throws ThingsboardException { @RequestBody AdminSettings adminSettings) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); adminSettings = checkNotNull(adminSettings);
adminSettings = checkNotNull(adminSettings); if (adminSettings.getKey().equals("mail")) {
if (adminSettings.getKey().equals("mail")) { if (!adminSettings.getJsonValue().has("password")) {
if (!adminSettings.getJsonValue().has("password")) { AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"));
AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail")); ((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
}
String email = getCurrentUser().getEmail();
mailService.sendTestMail(adminSettings.getJsonValue(), email);
} }
} catch (Exception e) { String email = getCurrentUser().getEmail();
throw handleException(e); mailService.sendTestMail(adminSettings.getJsonValue(), email);
} }
} }
@ -231,12 +203,8 @@ public class AdminController extends BaseController {
public void sendTestSms( public void sendTestSms(
@ApiParam(value = "A JSON value representing the Test SMS request.") @ApiParam(value = "A JSON value representing the Test SMS request.")
@RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException { @RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); smsService.sendTestSms(testSmsRequest);
smsService.sendTestSms(testSmsRequest);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get repository settings (getRepositorySettings)", @ApiOperation(value = "Get repository settings (getRepositorySettings)",
@ -244,16 +212,12 @@ public class AdminController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/repositorySettings") @GetMapping("/repositorySettings")
public RepositorySettings getRepositorySettings() throws ThingsboardException { public RepositorySettings getRepositorySettings() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); RepositorySettings versionControlSettings = checkNotNull(versionControlService.getVersionControlSettings(getTenantId()));
RepositorySettings versionControlSettings = checkNotNull(versionControlService.getVersionControlSettings(getTenantId())); versionControlSettings.setPassword(null);
versionControlSettings.setPassword(null); versionControlSettings.setPrivateKey(null);
versionControlSettings.setPrivateKey(null); versionControlSettings.setPrivateKeyPassword(null);
versionControlSettings.setPrivateKeyPassword(null); return versionControlSettings;
return versionControlSettings;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Check repository settings exists (repositorySettingsExists)", @ApiOperation(value = "Check repository settings exists (repositorySettingsExists)",
@ -261,12 +225,8 @@ public class AdminController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/repositorySettings/exists") @GetMapping("/repositorySettings/exists")
public Boolean repositorySettingsExists() throws ThingsboardException { public Boolean repositorySettingsExists() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); return versionControlService.getVersionControlSettings(getTenantId()) != null;
return versionControlService.getVersionControlSettings(getTenantId()) != null;
} catch (Exception e) {
throw handleException(e);
}
} }
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@ -307,13 +267,9 @@ public class AdminController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/repositorySettings", method = RequestMethod.DELETE) @RequestMapping(value = "/repositorySettings", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public DeferredResult<Void> deleteRepositorySettings() throws ThingsboardException { public DeferredResult<Void> deleteRepositorySettings() throws Exception {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE); return wrapFuture(versionControlService.deleteVersionControlSettings(getTenantId()));
return wrapFuture(versionControlService.deleteVersionControlSettings(getTenantId()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Check repository access (checkRepositoryAccess)", @ApiOperation(value = "Check repository access (checkRepositoryAccess)",
@ -322,14 +278,10 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/repositorySettings/checkAccess", method = RequestMethod.POST) @RequestMapping(value = "/repositorySettings/checkAccess", method = RequestMethod.POST)
public DeferredResult<Void> checkRepositoryAccess( public DeferredResult<Void> checkRepositoryAccess(
@ApiParam(value = "A JSON value representing the Repository Settings.") @ApiParam(value = "A JSON value representing the Repository Settings.")
@RequestBody RepositorySettings settings) throws ThingsboardException { @RequestBody RepositorySettings settings) throws Exception {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); settings = checkNotNull(settings);
settings = checkNotNull(settings); return wrapFuture(versionControlService.checkVersionControlAccess(getTenantId(), settings));
return wrapFuture(versionControlService.checkVersionControlAccess(getTenantId(), settings));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get auto commit settings (getAutoCommitSettings)", @ApiOperation(value = "Get auto commit settings (getAutoCommitSettings)",
@ -337,12 +289,8 @@ public class AdminController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/autoCommitSettings") @GetMapping("/autoCommitSettings")
public AutoCommitSettings getAutoCommitSettings() throws ThingsboardException { public AutoCommitSettings getAutoCommitSettings() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); return checkNotNull(autoCommitSettingsService.get(getTenantId()));
return checkNotNull(autoCommitSettingsService.get(getTenantId()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Check auto commit settings exists (autoCommitSettingsExists)", @ApiOperation(value = "Check auto commit settings exists (autoCommitSettingsExists)",
@ -350,12 +298,8 @@ public class AdminController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/autoCommitSettings/exists") @GetMapping("/autoCommitSettings/exists")
public Boolean autoCommitSettingsExists() throws ThingsboardException { public Boolean autoCommitSettingsExists() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); return autoCommitSettingsService.get(getTenantId()) != null;
return autoCommitSettingsService.get(getTenantId()) != null;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Creates or Updates the auto commit settings (saveAutoCommitSettings)", @ApiOperation(value = "Creates or Updates the auto commit settings (saveAutoCommitSettings)",
@ -374,12 +318,8 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/autoCommitSettings", method = RequestMethod.DELETE) @RequestMapping(value = "/autoCommitSettings", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public void deleteAutoCommitSettings() throws ThingsboardException { public void deleteAutoCommitSettings() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE);
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE); autoCommitSettingsService.delete(getTenantId());
autoCommitSettingsService.delete(getTenantId());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Check for new Platform Releases (checkUpdates)", @ApiOperation(value = "Check for new Platform Releases (checkUpdates)",
@ -389,11 +329,7 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/updates", method = RequestMethod.GET) @RequestMapping(value = "/updates", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public UpdateMessage checkUpdates() throws ThingsboardException { public UpdateMessage checkUpdates() throws ThingsboardException {
try { return updateService.checkUpdates();
return updateService.checkUpdates();
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get system info (getSystemInfo)", @ApiOperation(value = "Get system info (getSystemInfo)",

30
application/src/main/java/org/thingsboard/server/controller/AlarmController.java

@ -53,6 +53,7 @@ import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION;
import static org.thingsboard.server.controller.ControllerConstants.ALARM_INFO_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_INFO_DESCRIPTION;
@ -258,7 +259,7 @@ public class AlarmController extends BaseController {
@RequestParam(required = false) Long endTime, @RequestParam(required = false) Long endTime,
@ApiParam(value = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION) @ApiParam(value = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION)
@RequestParam(required = false) Boolean fetchOriginator @RequestParam(required = false) Boolean fetchOriginator
) throws ThingsboardException { ) throws ThingsboardException, ExecutionException, InterruptedException {
checkParameter("EntityId", strEntityId); checkParameter("EntityId", strEntityId);
checkParameter("EntityType", strEntityType); checkParameter("EntityType", strEntityType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
@ -275,11 +276,7 @@ public class AlarmController extends BaseController {
} }
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
try { return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, assigneeUserId, fetchOriginator)).get());
return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, assigneeUserId, fetchOriginator)).get());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get All Alarms (getAllAlarms)", @ApiOperation(value = "Get All Alarms (getAllAlarms)",
@ -314,7 +311,7 @@ public class AlarmController extends BaseController {
@RequestParam(required = false) Long endTime, @RequestParam(required = false) Long endTime,
@ApiParam(value = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION) @ApiParam(value = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION)
@RequestParam(required = false) Boolean fetchOriginator @RequestParam(required = false) Boolean fetchOriginator
) throws ThingsboardException { ) throws ThingsboardException, ExecutionException, InterruptedException {
AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus);
AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status); AlarmStatus alarmStatus = StringUtils.isEmpty(status) ? null : AlarmStatus.valueOf(status);
if (alarmSearchStatus != null && alarmStatus != null) { if (alarmSearchStatus != null && alarmStatus != null) {
@ -327,14 +324,10 @@ public class AlarmController extends BaseController {
} }
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
try { if (getCurrentUser().isCustomerUser()) {
if (getCurrentUser().isCustomerUser()) { return checkNotNull(alarmService.findCustomerAlarms(getCurrentUser().getTenantId(), getCurrentUser().getCustomerId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, assigneeUserId, fetchOriginator)).get());
return checkNotNull(alarmService.findCustomerAlarms(getCurrentUser().getTenantId(), getCurrentUser().getCustomerId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, assigneeUserId, fetchOriginator)).get()); } else {
} else { return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, assigneeUserId, fetchOriginator)).get());
return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(null, pageLink, alarmSearchStatus, alarmStatus, assigneeUserId, fetchOriginator)).get());
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -367,11 +360,8 @@ public class AlarmController extends BaseController {
"and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
} }
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
try { return alarmService.findHighestAlarmSeverity(getCurrentUser().getTenantId(), entityId, alarmSearchStatus,
return alarmService.findHighestAlarmSeverity(getCurrentUser().getTenantId(), entityId, alarmSearchStatus, alarmStatus, assigneeId); alarmStatus, assigneeId);
} catch (Exception e) {
throw handleException(e);
}
} }
} }

229
application/src/main/java/org/thingsboard/server/controller/AssetController.java

@ -60,6 +60,7 @@ import org.thingsboard.server.service.security.permission.Resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.ASSET_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ASSET_ID_PARAM_DESCRIPTION;
@ -108,12 +109,8 @@ public class AssetController extends BaseController {
public Asset getAssetById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) public Asset getAssetById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION)
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId); checkParameter(ASSET_ID, strAssetId);
try { AssetId assetId = new AssetId(toUUID(strAssetId));
AssetId assetId = new AssetId(toUUID(strAssetId)); return checkAssetId(assetId, Operation.READ);
return checkAssetId(assetId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Asset Info (getAssetInfoById)", @ApiOperation(value = "Get Asset Info (getAssetInfoById)",
@ -127,12 +124,8 @@ public class AssetController extends BaseController {
public AssetInfo getAssetInfoById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) public AssetInfo getAssetInfoById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION)
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId); checkParameter(ASSET_ID, strAssetId);
try { AssetId assetId = new AssetId(toUUID(strAssetId));
AssetId assetId = new AssetId(toUUID(strAssetId)); return checkAssetInfoId(assetId, Operation.READ);
return checkAssetInfoId(assetId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Asset (saveAsset)", @ApiOperation(value = "Create Or Update Asset (saveAsset)",
@ -228,16 +221,12 @@ public class AssetController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink)); } else {
} else { return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink));
return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -262,19 +251,15 @@ public class AssetController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(assetService.findAssetInfosByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(assetService.findAssetInfosByTenantIdAndType(tenantId, type, pageLink)); } else if (assetProfileId != null && assetProfileId.length() > 0) {
} else if (assetProfileId != null && assetProfileId.length() > 0) { AssetProfileId profileId = new AssetProfileId(toUUID(assetProfileId));
AssetProfileId profileId = new AssetProfileId(toUUID(assetProfileId)); return checkNotNull(assetService.findAssetInfosByTenantIdAndAssetProfileId(tenantId, profileId, pageLink));
return checkNotNull(assetService.findAssetInfosByTenantIdAndAssetProfileId(tenantId, profileId, pageLink)); } else {
} else { return checkNotNull(assetService.findAssetInfosByTenantId(tenantId, pageLink));
return checkNotNull(assetService.findAssetInfosByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -287,12 +272,8 @@ public class AssetController extends BaseController {
public Asset getTenantAsset( public Asset getTenantAsset(
@ApiParam(value = ASSET_NAME_DESCRIPTION) @ApiParam(value = ASSET_NAME_DESCRIPTION)
@RequestParam String assetName) throws ThingsboardException { @RequestParam String assetName) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(assetService.findAssetByTenantIdAndName(tenantId, assetName));
return checkNotNull(assetService.findAssetByTenantIdAndName(tenantId, assetName));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Customer Assets (getCustomerAssets)", @ApiOperation(value = "Get Customer Assets (getCustomerAssets)",
@ -317,18 +298,14 @@ public class AssetController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); } else {
} else { return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -356,21 +333,17 @@ public class AssetController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); } else if (assetProfileId != null && assetProfileId.length() > 0) {
} else if (assetProfileId != null && assetProfileId.length() > 0) { AssetProfileId profileId = new AssetProfileId(toUUID(assetProfileId));
AssetProfileId profileId = new AssetProfileId(toUUID(assetProfileId)); return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerIdAndAssetProfileId(tenantId, customerId, profileId, pageLink));
return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerIdAndAssetProfileId(tenantId, customerId, profileId, pageLink)); } else {
} else { return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -381,26 +354,22 @@ public class AssetController extends BaseController {
@ResponseBody @ResponseBody
public List<Asset> getAssetsByIds( public List<Asset> getAssetsByIds(
@ApiParam(value = "A list of assets ids, separated by comma ','") @ApiParam(value = "A list of assets ids, separated by comma ','")
@RequestParam("assetIds") String[] strAssetIds) throws ThingsboardException { @RequestParam("assetIds") String[] strAssetIds) throws ThingsboardException, ExecutionException, InterruptedException {
checkArrayParameter("assetIds", strAssetIds); checkArrayParameter("assetIds", strAssetIds);
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); CustomerId customerId = user.getCustomerId();
CustomerId customerId = user.getCustomerId(); List<AssetId> assetIds = new ArrayList<>();
List<AssetId> assetIds = new ArrayList<>(); for (String strAssetId : strAssetIds) {
for (String strAssetId : strAssetIds) { assetIds.add(new AssetId(toUUID(strAssetId)));
assetIds.add(new AssetId(toUUID(strAssetId)));
}
ListenableFuture<List<Asset>> assets;
if (customerId == null || customerId.isNullUid()) {
assets = assetService.findAssetsByTenantIdAndIdsAsync(tenantId, assetIds);
} else {
assets = assetService.findAssetsByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, assetIds);
}
return checkNotNull(assets.get());
} catch (Exception e) {
throw handleException(e);
} }
ListenableFuture<List<Asset>> assets;
if (customerId == null || customerId.isNullUid()) {
assets = assetService.findAssetsByTenantIdAndIdsAsync(tenantId, assetIds);
} else {
assets = assetService.findAssetsByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, assetIds);
}
return checkNotNull(assets.get());
} }
@ApiOperation(value = "Find related assets (findByQuery)", @ApiOperation(value = "Find related assets (findByQuery)",
@ -410,25 +379,21 @@ public class AssetController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assets", method = RequestMethod.POST) @RequestMapping(value = "/assets", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public List<Asset> findByQuery(@RequestBody AssetSearchQuery query) throws ThingsboardException { public List<Asset> findByQuery(@RequestBody AssetSearchQuery query) throws ThingsboardException, ExecutionException, InterruptedException {
checkNotNull(query); checkNotNull(query);
checkNotNull(query.getParameters()); checkNotNull(query.getParameters());
checkNotNull(query.getAssetTypes()); checkNotNull(query.getAssetTypes());
checkEntityId(query.getParameters().getEntityId(), Operation.READ); checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try { List<Asset> assets = checkNotNull(assetService.findAssetsByQuery(getTenantId(), query).get());
List<Asset> assets = checkNotNull(assetService.findAssetsByQuery(getTenantId(), query).get()); assets = assets.stream().filter(asset -> {
assets = assets.stream().filter(asset -> { try {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset);
accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset); return true;
return true; } catch (ThingsboardException e) {
} catch (ThingsboardException e) { return false;
return false; }
} }).collect(Collectors.toList());
}).collect(Collectors.toList()); return assets;
return assets;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Asset Types (getAssetTypes)", @ApiOperation(value = "Get Asset Types (getAssetTypes)",
@ -436,15 +401,11 @@ public class AssetController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/types", method = RequestMethod.GET) @RequestMapping(value = "/asset/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<EntitySubtype> getAssetTypes() throws ThingsboardException { public List<EntitySubtype> getAssetTypes() throws ThingsboardException, ExecutionException, InterruptedException {
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); ListenableFuture<List<EntitySubtype>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
ListenableFuture<List<EntitySubtype>> assetTypes = assetService.findAssetTypesByTenantId(tenantId); return checkNotNull(assetTypes.get());
return checkNotNull(assetTypes.get());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Assign asset to edge (assignAssetToEdge)", @ApiOperation(value = "Assign asset to edge (assignAssetToEdge)",
@ -520,33 +481,29 @@ public class AssetController extends BaseController {
@ApiParam(value = "Timestamp. Assets with creation time after it won't be queried") @ApiParam(value = "Timestamp. Assets with creation time after it won't be queried")
@RequestParam(required = false) Long endTime) throws ThingsboardException { @RequestParam(required = false) Long endTime) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ);
checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); PageData<Asset> nonFilteredResult;
PageData<Asset> nonFilteredResult; if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { nonFilteredResult = assetService.findAssetsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink);
nonFilteredResult = assetService.findAssetsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink); } else {
} else { nonFilteredResult = assetService.findAssetsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
nonFilteredResult = assetService.findAssetsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
}
List<Asset> filteredAssets = nonFilteredResult.getData().stream().filter(asset -> {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset);
return true;
} catch (ThingsboardException e) {
return false;
}
}).collect(Collectors.toList());
PageData<Asset> filteredResult = new PageData<>(filteredAssets,
nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalElements(),
nonFilteredResult.hasNext());
return checkNotNull(filteredResult);
} catch (Exception e) {
throw handleException(e);
} }
List<Asset> filteredAssets = nonFilteredResult.getData().stream().filter(asset -> {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset);
return true;
} catch (ThingsboardException e) {
return false;
}
}).collect(Collectors.toList());
PageData<Asset> filteredResult = new PageData<>(filteredAssets,
nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalElements(),
nonFilteredResult.hasNext());
return checkNotNull(filteredResult);
} }
@ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)", @ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)",

38
application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java

@ -78,12 +78,8 @@ public class AssetProfileController extends BaseController {
@ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { @PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException {
checkParameter(ASSET_PROFILE_ID, strAssetProfileId); checkParameter(ASSET_PROFILE_ID, strAssetProfileId);
try { AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId));
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); return checkAssetProfileId(assetProfileId, Operation.READ);
return checkAssetProfileId(assetProfileId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)", @ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)",
@ -97,12 +93,8 @@ public class AssetProfileController extends BaseController {
@ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { @PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException {
checkParameter(ASSET_PROFILE_ID, strAssetProfileId); checkParameter(ASSET_PROFILE_ID, strAssetProfileId);
try { AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId));
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); return new AssetProfileInfo(checkAssetProfileId(assetProfileId, Operation.READ));
return new AssetProfileInfo(checkAssetProfileId(assetProfileId, Operation.READ));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)", @ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)",
@ -113,11 +105,7 @@ public class AssetProfileController extends BaseController {
@RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET) @RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public AssetProfileInfo getDefaultAssetProfileInfo() throws ThingsboardException { public AssetProfileInfo getDefaultAssetProfileInfo() throws ThingsboardException {
try { return checkNotNull(assetProfileService.findDefaultAssetProfileInfo(getTenantId()));
return checkNotNull(assetProfileService.findDefaultAssetProfileInfo(getTenantId()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Asset Profile (saveAssetProfile)", @ApiOperation(value = "Create Or Update Asset Profile (saveAssetProfile)",
@ -191,12 +179,8 @@ public class AssetProfileController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(assetProfileService.findAssetProfiles(getTenantId(), pageLink));
return checkNotNull(assetProfileService.findAssetProfiles(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)", @ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)",
@ -217,11 +201,7 @@ public class AssetProfileController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(assetProfileService.findAssetProfileInfos(getTenantId(), pageLink));
return checkNotNull(assetProfileService.findAssetProfileInfos(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
} }

56
application/src/main/java/org/thingsboard/server/controller/AuditLogController.java

@ -97,15 +97,11 @@ public class AuditLogController extends BaseController {
@RequestParam(required = false) Long endTime, @RequestParam(required = false) Long endTime,
@ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION)
@RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException {
try { checkParameter("CustomerId", strCustomerId);
checkParameter("CustomerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr);
List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); return checkNotNull(auditLogService.findAuditLogsByTenantIdAndCustomerId(tenantId, new CustomerId(UUID.fromString(strCustomerId)), actionTypes, pageLink));
return checkNotNull(auditLogService.findAuditLogsByTenantIdAndCustomerId(tenantId, new CustomerId(UUID.fromString(strCustomerId)), actionTypes, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)", @ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)",
@ -135,15 +131,11 @@ public class AuditLogController extends BaseController {
@RequestParam(required = false) Long endTime, @RequestParam(required = false) Long endTime,
@ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION)
@RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException {
try { checkParameter("UserId", strUserId);
checkParameter("UserId", strUserId); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr);
List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); return checkNotNull(auditLogService.findAuditLogsByTenantIdAndUserId(tenantId, new UserId(UUID.fromString(strUserId)), actionTypes, pageLink));
return checkNotNull(auditLogService.findAuditLogsByTenantIdAndUserId(tenantId, new UserId(UUID.fromString(strUserId)), actionTypes, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get audit logs by entity id (getAuditLogsByEntityId)", @ApiOperation(value = "Get audit logs by entity id (getAuditLogsByEntityId)",
@ -176,16 +168,12 @@ public class AuditLogController extends BaseController {
@RequestParam(required = false) Long endTime, @RequestParam(required = false) Long endTime,
@ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION)
@RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException {
try { checkParameter("EntityId", strEntityId);
checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType);
checkParameter("EntityType", strEntityType); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr);
List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); return checkNotNull(auditLogService.findAuditLogsByTenantIdAndEntityId(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), actionTypes, pageLink));
return checkNotNull(auditLogService.findAuditLogsByTenantIdAndEntityId(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), actionTypes, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get all audit logs (getAuditLogs)", @ApiOperation(value = "Get all audit logs (getAuditLogs)",
@ -212,14 +200,10 @@ public class AuditLogController extends BaseController {
@RequestParam(required = false) Long endTime, @RequestParam(required = false) Long endTime,
@ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION)
@RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr);
List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); return checkNotNull(auditLogService.findAuditLogsByTenantId(tenantId, actionTypes, pageLink));
return checkNotNull(auditLogService.findAuditLogsByTenantId(tenantId, actionTypes, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
private List<ActionType> parseActionTypesStr(String actionTypesStr) { private List<ActionType> parseActionTypesStr(String actionTypesStr) {

164
application/src/main/java/org/thingsboard/server/controller/AuthController.java

@ -92,12 +92,8 @@ public class AuthController extends BaseController {
@RequestMapping(value = "/auth/user", method = RequestMethod.GET) @RequestMapping(value = "/auth/user", method = RequestMethod.GET)
public @ResponseBody public @ResponseBody
User getUser() throws ThingsboardException { User getUser() throws ThingsboardException {
try { SecurityUser securityUser = getCurrentUser();
SecurityUser securityUser = getCurrentUser(); return userService.findUserById(securityUser.getTenantId(), securityUser.getId());
return userService.findUserById(securityUser.getTenantId(), securityUser.getId());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Logout (logout)", @ApiOperation(value = "Logout (logout)",
@ -117,31 +113,27 @@ public class AuthController extends BaseController {
public ObjectNode changePassword( public ObjectNode changePassword(
@ApiParam(value = "Change Password Request") @ApiParam(value = "Change Password Request")
@RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException { @RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException {
try { String currentPassword = changePasswordRequest.getCurrentPassword();
String currentPassword = changePasswordRequest.getCurrentPassword(); String newPassword = changePasswordRequest.getNewPassword();
String newPassword = changePasswordRequest.getNewPassword(); SecurityUser securityUser = getCurrentUser();
SecurityUser securityUser = getCurrentUser(); UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, securityUser.getId());
UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, securityUser.getId()); if (!passwordEncoder.matches(currentPassword, userCredentials.getPassword())) {
if (!passwordEncoder.matches(currentPassword, userCredentials.getPassword())) { throw new ThingsboardException("Current password doesn't match!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
throw new ThingsboardException("Current password doesn't match!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); }
} systemSecurityService.validatePassword(securityUser.getTenantId(), newPassword, userCredentials);
systemSecurityService.validatePassword(securityUser.getTenantId(), newPassword, userCredentials); if (passwordEncoder.matches(newPassword, userCredentials.getPassword())) {
if (passwordEncoder.matches(newPassword, userCredentials.getPassword())) { throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); }
} userCredentials.setPassword(passwordEncoder.encode(newPassword));
userCredentials.setPassword(passwordEncoder.encode(newPassword)); userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials);
userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials);
sendEntityNotificationMsg(getTenantId(), userCredentials.getUserId(), EdgeEventActionType.CREDENTIALS_UPDATED); sendEntityNotificationMsg(getTenantId(), userCredentials.getUserId(), EdgeEventActionType.CREDENTIALS_UPDATED);
eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId())); eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId()));
ObjectNode response = JacksonUtil.newObjectNode(); ObjectNode response = JacksonUtil.newObjectNode();
response.put("token", tokenFactory.createAccessJwtToken(securityUser).getToken()); response.put("token", tokenFactory.createAccessJwtToken(securityUser).getToken());
response.put("refreshToken", tokenFactory.createRefreshToken(securityUser).getToken()); response.put("refreshToken", tokenFactory.createRefreshToken(securityUser).getToken());
return response; return response;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get the current User password policy (getUserPasswordPolicy)", @ApiOperation(value = "Get the current User password policy (getUserPasswordPolicy)",
@ -149,13 +141,9 @@ public class AuthController extends BaseController {
@RequestMapping(value = "/noauth/userPasswordPolicy", method = RequestMethod.GET) @RequestMapping(value = "/noauth/userPasswordPolicy", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public UserPasswordPolicy getUserPasswordPolicy() throws ThingsboardException { public UserPasswordPolicy getUserPasswordPolicy() throws ThingsboardException {
try { SecuritySettings securitySettings =
SecuritySettings securitySettings = checkNotNull(systemSecurityService.getSecuritySettings(TenantId.SYS_TENANT_ID));
checkNotNull(systemSecurityService.getSecuritySettings(TenantId.SYS_TENANT_ID)); return securitySettings.getPasswordPolicy();
return securitySettings.getPasswordPolicy();
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Check Activate User Token (checkActivateToken)", @ApiOperation(value = "Check Activate User Token (checkActivateToken)",
@ -255,34 +243,30 @@ public class AuthController extends BaseController {
@RequestBody ActivateUserRequest activateRequest, @RequestBody ActivateUserRequest activateRequest,
@RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail,
HttpServletRequest request) throws ThingsboardException { HttpServletRequest request) throws ThingsboardException {
try { String activateToken = activateRequest.getActivateToken();
String activateToken = activateRequest.getActivateToken(); String password = activateRequest.getPassword();
String password = activateRequest.getPassword(); systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, null);
systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, null); String encodedPassword = passwordEncoder.encode(password);
String encodedPassword = passwordEncoder.encode(password); UserCredentials credentials = userService.activateUserCredentials(TenantId.SYS_TENANT_ID, activateToken, encodedPassword);
UserCredentials credentials = userService.activateUserCredentials(TenantId.SYS_TENANT_ID, activateToken, encodedPassword); User user = userService.findUserById(TenantId.SYS_TENANT_ID, credentials.getUserId());
User user = userService.findUserById(TenantId.SYS_TENANT_ID, credentials.getUserId()); UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail()); SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal);
SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal); userService.setUserCredentialsEnabled(user.getTenantId(), user.getId(), true);
userService.setUserCredentialsEnabled(user.getTenantId(), user.getId(), true); String baseUrl = systemSecurityService.getBaseUrl(user.getTenantId(), user.getCustomerId(), request);
String baseUrl = systemSecurityService.getBaseUrl(user.getTenantId(), user.getCustomerId(), request); String loginUrl = String.format("%s/login", baseUrl);
String loginUrl = String.format("%s/login", baseUrl); String email = user.getEmail();
String email = user.getEmail();
if (sendActivationMail) { if (sendActivationMail) {
try { try {
mailService.sendAccountActivatedEmail(loginUrl, email); mailService.sendAccountActivatedEmail(loginUrl, email);
} catch (Exception e) { } catch (Exception e) {
log.info("Unable to send account activation email [{}]", e.getMessage()); log.info("Unable to send account activation email [{}]", e.getMessage());
}
} }
}
sendEntityNotificationMsg(user.getTenantId(), user.getId(), EdgeEventActionType.CREDENTIALS_UPDATED); sendEntityNotificationMsg(user.getTenantId(), user.getId(), EdgeEventActionType.CREDENTIALS_UPDATED);
return tokenFactory.createTokenPair(securityUser); return tokenFactory.createTokenPair(securityUser);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Reset password (resetPassword)", @ApiOperation(value = "Reset password (resetPassword)",
@ -296,46 +280,38 @@ public class AuthController extends BaseController {
@ApiParam(value = "Reset password request.") @ApiParam(value = "Reset password request.")
@RequestBody ResetPasswordRequest resetPasswordRequest, @RequestBody ResetPasswordRequest resetPasswordRequest,
HttpServletRequest request) throws ThingsboardException { HttpServletRequest request) throws ThingsboardException {
try { String resetToken = resetPasswordRequest.getResetToken();
String resetToken = resetPasswordRequest.getResetToken(); String password = resetPasswordRequest.getPassword();
String password = resetPasswordRequest.getPassword(); UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken);
UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); if (userCredentials != null) {
if (userCredentials != null) { systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, userCredentials);
systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, userCredentials); if (passwordEncoder.matches(password, userCredentials.getPassword())) {
if (passwordEncoder.matches(password, userCredentials.getPassword())) { throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); }
} String encodedPassword = passwordEncoder.encode(password);
String encodedPassword = passwordEncoder.encode(password); userCredentials.setPassword(encodedPassword);
userCredentials.setPassword(encodedPassword); userCredentials.setResetToken(null);
userCredentials.setResetToken(null); userCredentials = userService.replaceUserCredentials(TenantId.SYS_TENANT_ID, userCredentials);
userCredentials = userService.replaceUserCredentials(TenantId.SYS_TENANT_ID, userCredentials); User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId());
User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId()); UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail()); SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), principal);
SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), principal); String baseUrl = systemSecurityService.getBaseUrl(user.getTenantId(), user.getCustomerId(), request);
String baseUrl = systemSecurityService.getBaseUrl(user.getTenantId(), user.getCustomerId(), request); String loginUrl = String.format("%s/login", baseUrl);
String loginUrl = String.format("%s/login", baseUrl); String email = user.getEmail();
String email = user.getEmail(); mailService.sendPasswordWasResetEmail(loginUrl, email);
mailService.sendPasswordWasResetEmail(loginUrl, email);
eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId())); eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId()));
return tokenFactory.createTokenPair(securityUser); return tokenFactory.createTokenPair(securityUser);
} else { } else {
throw new ThingsboardException("Invalid reset token!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); throw new ThingsboardException("Invalid reset token!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
} catch (Exception e) {
throw handleException(e);
} }
} }
private void logLogoutAction(HttpServletRequest request) throws ThingsboardException { private void logLogoutAction(HttpServletRequest request) throws ThingsboardException {
try { var user = getCurrentUser();
var user = getCurrentUser(); systemSecurityService.logLoginAction(user, new RestAuthenticationDetails(request), ActionType.LOGOUT, null);
systemSecurityService.logLoginAction(user, new RestAuthenticationDetails(request), ActionType.LOGOUT, null); eventPublisher.publishEvent(new UserSessionInvalidationEvent(user.getSessionId()));
eventPublisher.publishEvent(new UserSessionInvalidationEvent(user.getSessionId()));
} catch (Exception e) {
throw handleException(e);
}
} }
private TbRateLimits getTbRateLimits(UserId userId) { private TbRateLimits getTbRateLimits(UserId userId) {

24
application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java

@ -57,11 +57,7 @@ public class ComponentDescriptorController extends BaseController {
@ApiParam(value = "Component Descriptor class name", required = true) @ApiParam(value = "Component Descriptor class name", required = true)
@PathVariable("componentDescriptorClazz") String strComponentDescriptorClazz) throws ThingsboardException { @PathVariable("componentDescriptorClazz") String strComponentDescriptorClazz) throws ThingsboardException {
checkParameter("strComponentDescriptorClazz", strComponentDescriptorClazz); checkParameter("strComponentDescriptorClazz", strComponentDescriptorClazz);
try { return checkComponentDescriptorByClazz(strComponentDescriptorClazz);
return checkComponentDescriptorByClazz(strComponentDescriptorClazz);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByType)", @ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByType)",
@ -76,11 +72,7 @@ public class ComponentDescriptorController extends BaseController {
@ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE") @ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE")
@RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException { @RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException {
checkParameter("componentType", strComponentType); checkParameter("componentType", strComponentType);
try { return checkComponentDescriptorsByType(ComponentType.valueOf(strComponentType), getRuleChainType(strRuleChainType));
return checkComponentDescriptorsByType(ComponentType.valueOf(strComponentType), getRuleChainType(strRuleChainType));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByTypes)", @ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByTypes)",
@ -95,15 +87,11 @@ public class ComponentDescriptorController extends BaseController {
@ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE") @ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE")
@RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException { @RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException {
checkArrayParameter("componentTypes", strComponentTypes); checkArrayParameter("componentTypes", strComponentTypes);
try { Set<ComponentType> componentTypes = new HashSet<>();
Set<ComponentType> componentTypes = new HashSet<>(); for (String strComponentType : strComponentTypes) {
for (String strComponentType : strComponentTypes) { componentTypes.add(ComponentType.valueOf(strComponentType));
componentTypes.add(ComponentType.valueOf(strComponentType));
}
return checkComponentDescriptorsByTypes(componentTypes, getRuleChainType(strRuleChainType));
} catch (Exception e) {
throw handleException(e);
} }
return checkComponentDescriptorsByTypes(componentTypes, getRuleChainType(strRuleChainType));
} }
private RuleChainType getRuleChainType(String strRuleChainType) { private RuleChainType getRuleChainType(String strRuleChainType) {

58
application/src/main/java/org/thingsboard/server/controller/CustomerController.java

@ -79,16 +79,12 @@ public class CustomerController extends BaseController {
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(CUSTOMER_ID, strCustomerId);
try { CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); Customer customer = checkCustomerId(customerId, Operation.READ);
Customer customer = checkCustomerId(customerId, Operation.READ); if (!customer.getAdditionalInfo().isNull()) {
if (!customer.getAdditionalInfo().isNull()) { processDashboardIdFromAdditionalInfo((ObjectNode) customer.getAdditionalInfo(), HOME_DASHBOARD);
processDashboardIdFromAdditionalInfo((ObjectNode) customer.getAdditionalInfo(), HOME_DASHBOARD);
}
return customer;
} catch (Exception e) {
throw handleException(e);
} }
return customer;
} }
@ -102,17 +98,13 @@ public class CustomerController extends BaseController {
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(CUSTOMER_ID, strCustomerId);
try { CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); Customer customer = checkCustomerId(customerId, Operation.READ);
Customer customer = checkCustomerId(customerId, Operation.READ); ObjectMapper objectMapper = new ObjectMapper();
ObjectMapper objectMapper = new ObjectMapper(); ObjectNode infoObject = objectMapper.createObjectNode();
ObjectNode infoObject = objectMapper.createObjectNode(); infoObject.put("title", customer.getTitle());
infoObject.put("title", customer.getTitle()); infoObject.put(IS_PUBLIC, customer.isPublic());
infoObject.put(IS_PUBLIC, customer.isPublic()); return infoObject;
return infoObject;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Customer Title (getCustomerTitleById)", @ApiOperation(value = "Get Customer Title (getCustomerTitleById)",
@ -125,13 +117,9 @@ public class CustomerController extends BaseController {
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(CUSTOMER_ID, strCustomerId);
try { CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); Customer customer = checkCustomerId(customerId, Operation.READ);
Customer customer = checkCustomerId(customerId, Operation.READ); return customer.getTitle();
return customer.getTitle();
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create or update Customer (saveCustomer)", @ApiOperation(value = "Create or update Customer (saveCustomer)",
@ -182,13 +170,9 @@ public class CustomerController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(customerService.findCustomersByTenantId(tenantId, pageLink));
return checkNotNull(customerService.findCustomersByTenantId(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Tenant Customer by Customer title (getTenantCustomer)", @ApiOperation(value = "Get Tenant Customer by Customer title (getTenantCustomer)",
@ -199,11 +183,7 @@ public class CustomerController extends BaseController {
public Customer getTenantCustomer( public Customer getTenantCustomer(
@ApiParam(value = "A string value representing the Customer title.") @ApiParam(value = "A string value representing the Customer title.")
@RequestParam String customerTitle) throws ThingsboardException { @RequestParam String customerTitle) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId(); TenantId tenantId = getCurrentUser().getTenantId();
return checkNotNull(customerService.findCustomerByTenantIdAndTitle(tenantId, customerTitle), "Customer with title [" + customerTitle + "] is not found"); return checkNotNull(customerService.findCustomerByTenantIdAndTitle(tenantId, customerTitle), "Customer with title [" + customerTitle + "] is not found");
} catch (Exception e) {
throw handleException(e);
}
} }
} }

240
application/src/main/java/org/thingsboard/server/controller/DashboardController.java

@ -140,12 +140,8 @@ public class DashboardController extends BaseController {
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId); checkParameter(DASHBOARD_ID, strDashboardId);
try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); return checkDashboardInfoId(dashboardId, Operation.READ);
return checkDashboardInfoId(dashboardId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Dashboard (getDashboardById)", @ApiOperation(value = "Get Dashboard (getDashboardById)",
@ -159,12 +155,8 @@ public class DashboardController extends BaseController {
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId); checkParameter(DASHBOARD_ID, strDashboardId);
try { DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); return checkDashboardId(dashboardId, Operation.READ);
return checkDashboardId(dashboardId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Dashboard (saveDashboard)", @ApiOperation(value = "Create Or Update Dashboard (saveDashboard)",
@ -362,14 +354,10 @@ public class DashboardController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId));
TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); checkTenantId(tenantId, Operation.READ);
checkTenantId(tenantId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink));
return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)", @ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)",
@ -392,16 +380,12 @@ public class DashboardController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (mobile != null && mobile) {
if (mobile != null && mobile) { return checkNotNull(dashboardService.findMobileDashboardsByTenantId(tenantId, pageLink));
return checkNotNull(dashboardService.findMobileDashboardsByTenantId(tenantId, pageLink)); } else {
} else { return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink));
return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -428,18 +412,14 @@ public class DashboardController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(CUSTOMER_ID, strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (mobile != null && mobile) {
if (mobile != null && mobile) { return checkNotNull(dashboardService.findMobileDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(dashboardService.findMobileDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); } else {
} else { return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -453,31 +433,27 @@ public class DashboardController extends BaseController {
@RequestMapping(value = "/dashboard/home", method = RequestMethod.GET) @RequestMapping(value = "/dashboard/home", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public HomeDashboard getHomeDashboard() throws ThingsboardException { public HomeDashboard getHomeDashboard() throws ThingsboardException {
try { SecurityUser securityUser = getCurrentUser();
SecurityUser securityUser = getCurrentUser(); if (securityUser.isSystemAdmin()) {
if (securityUser.isSystemAdmin()) { return null;
return null; }
User user = userService.findUserById(securityUser.getTenantId(), securityUser.getId());
JsonNode additionalInfo = user.getAdditionalInfo();
HomeDashboard homeDashboard;
homeDashboard = extractHomeDashboardFromAdditionalInfo(additionalInfo);
if (homeDashboard == null) {
if (securityUser.isCustomerUser()) {
Customer customer = customerService.findCustomerById(securityUser.getTenantId(), securityUser.getCustomerId());
additionalInfo = customer.getAdditionalInfo();
homeDashboard = extractHomeDashboardFromAdditionalInfo(additionalInfo);
} }
User user = userService.findUserById(securityUser.getTenantId(), securityUser.getId());
JsonNode additionalInfo = user.getAdditionalInfo();
HomeDashboard homeDashboard;
homeDashboard = extractHomeDashboardFromAdditionalInfo(additionalInfo);
if (homeDashboard == null) { if (homeDashboard == null) {
if (securityUser.isCustomerUser()) { Tenant tenant = tenantService.findTenantById(securityUser.getTenantId());
Customer customer = customerService.findCustomerById(securityUser.getTenantId(), securityUser.getCustomerId()); additionalInfo = tenant.getAdditionalInfo();
additionalInfo = customer.getAdditionalInfo(); homeDashboard = extractHomeDashboardFromAdditionalInfo(additionalInfo);
homeDashboard = extractHomeDashboardFromAdditionalInfo(additionalInfo);
}
if (homeDashboard == null) {
Tenant tenant = tenantService.findTenantById(securityUser.getTenantId());
additionalInfo = tenant.getAdditionalInfo();
homeDashboard = extractHomeDashboardFromAdditionalInfo(additionalInfo);
}
} }
return homeDashboard;
} catch (Exception e) {
throw handleException(e);
} }
return homeDashboard;
} }
@ApiOperation(value = "Get Home Dashboard Info (getHomeDashboardInfo)", @ApiOperation(value = "Get Home Dashboard Info (getHomeDashboardInfo)",
@ -490,31 +466,27 @@ public class DashboardController extends BaseController {
@RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET) @RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public HomeDashboardInfo getHomeDashboardInfo() throws ThingsboardException { public HomeDashboardInfo getHomeDashboardInfo() throws ThingsboardException {
try { SecurityUser securityUser = getCurrentUser();
SecurityUser securityUser = getCurrentUser(); if (securityUser.isSystemAdmin()) {
if (securityUser.isSystemAdmin()) { return null;
return null; }
User user = userService.findUserById(securityUser.getTenantId(), securityUser.getId());
JsonNode additionalInfo = user.getAdditionalInfo();
HomeDashboardInfo homeDashboardInfo;
homeDashboardInfo = extractHomeDashboardInfoFromAdditionalInfo(additionalInfo);
if (homeDashboardInfo == null) {
if (securityUser.isCustomerUser()) {
Customer customer = customerService.findCustomerById(securityUser.getTenantId(), securityUser.getCustomerId());
additionalInfo = customer.getAdditionalInfo();
homeDashboardInfo = extractHomeDashboardInfoFromAdditionalInfo(additionalInfo);
} }
User user = userService.findUserById(securityUser.getTenantId(), securityUser.getId());
JsonNode additionalInfo = user.getAdditionalInfo();
HomeDashboardInfo homeDashboardInfo;
homeDashboardInfo = extractHomeDashboardInfoFromAdditionalInfo(additionalInfo);
if (homeDashboardInfo == null) { if (homeDashboardInfo == null) {
if (securityUser.isCustomerUser()) { Tenant tenant = tenantService.findTenantById(securityUser.getTenantId());
Customer customer = customerService.findCustomerById(securityUser.getTenantId(), securityUser.getCustomerId()); additionalInfo = tenant.getAdditionalInfo();
additionalInfo = customer.getAdditionalInfo(); homeDashboardInfo = extractHomeDashboardInfoFromAdditionalInfo(additionalInfo);
homeDashboardInfo = extractHomeDashboardInfoFromAdditionalInfo(additionalInfo);
}
if (homeDashboardInfo == null) {
Tenant tenant = tenantService.findTenantById(securityUser.getTenantId());
additionalInfo = tenant.getAdditionalInfo();
homeDashboardInfo = extractHomeDashboardInfoFromAdditionalInfo(additionalInfo);
}
} }
return homeDashboardInfo;
} catch (Exception e) {
throw handleException(e);
} }
return homeDashboardInfo;
} }
@ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", @ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
@ -525,22 +497,18 @@ public class DashboardController extends BaseController {
@RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET) @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public HomeDashboardInfo getTenantHomeDashboardInfo() throws ThingsboardException { public HomeDashboardInfo getTenantHomeDashboardInfo() throws ThingsboardException {
try { Tenant tenant = tenantService.findTenantById(getTenantId());
Tenant tenant = tenantService.findTenantById(getTenantId()); JsonNode additionalInfo = tenant.getAdditionalInfo();
JsonNode additionalInfo = tenant.getAdditionalInfo(); DashboardId dashboardId = null;
DashboardId dashboardId = null; boolean hideDashboardToolbar = true;
boolean hideDashboardToolbar = true; if (additionalInfo != null && additionalInfo.has(HOME_DASHBOARD_ID) && !additionalInfo.get(HOME_DASHBOARD_ID).isNull()) {
if (additionalInfo != null && additionalInfo.has(HOME_DASHBOARD_ID) && !additionalInfo.get(HOME_DASHBOARD_ID).isNull()) { String strDashboardId = additionalInfo.get(HOME_DASHBOARD_ID).asText();
String strDashboardId = additionalInfo.get(HOME_DASHBOARD_ID).asText(); dashboardId = new DashboardId(toUUID(strDashboardId));
dashboardId = new DashboardId(toUUID(strDashboardId)); if (additionalInfo.has(HOME_DASHBOARD_HIDE_TOOLBAR)) {
if (additionalInfo.has(HOME_DASHBOARD_HIDE_TOOLBAR)) { hideDashboardToolbar = additionalInfo.get(HOME_DASHBOARD_HIDE_TOOLBAR).asBoolean();
hideDashboardToolbar = additionalInfo.get(HOME_DASHBOARD_HIDE_TOOLBAR).asBoolean();
}
} }
return new HomeDashboardInfo(dashboardId, hideDashboardToolbar);
} catch (Exception e) {
throw handleException(e);
} }
return new HomeDashboardInfo(dashboardId, hideDashboardToolbar);
} }
@ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", @ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
@ -554,27 +522,23 @@ public class DashboardController extends BaseController {
@ApiParam(value = "A JSON object that represents home dashboard id and other parameters", required = true) @ApiParam(value = "A JSON object that represents home dashboard id and other parameters", required = true)
@RequestBody HomeDashboardInfo homeDashboardInfo) throws ThingsboardException { @RequestBody HomeDashboardInfo homeDashboardInfo) throws ThingsboardException {
try { if (homeDashboardInfo.getDashboardId() != null) {
if (homeDashboardInfo.getDashboardId() != null) { checkDashboardId(homeDashboardInfo.getDashboardId(), Operation.READ);
checkDashboardId(homeDashboardInfo.getDashboardId(), Operation.READ); }
} Tenant tenant = tenantService.findTenantById(getTenantId());
Tenant tenant = tenantService.findTenantById(getTenantId()); JsonNode additionalInfo = tenant.getAdditionalInfo();
JsonNode additionalInfo = tenant.getAdditionalInfo(); if (additionalInfo == null || !(additionalInfo instanceof ObjectNode)) {
if (additionalInfo == null || !(additionalInfo instanceof ObjectNode)) { additionalInfo = JacksonUtil.OBJECT_MAPPER.createObjectNode();
additionalInfo = JacksonUtil.OBJECT_MAPPER.createObjectNode(); }
} if (homeDashboardInfo.getDashboardId() != null) {
if (homeDashboardInfo.getDashboardId() != null) { ((ObjectNode) additionalInfo).put(HOME_DASHBOARD_ID, homeDashboardInfo.getDashboardId().getId().toString());
((ObjectNode) additionalInfo).put(HOME_DASHBOARD_ID, homeDashboardInfo.getDashboardId().getId().toString()); ((ObjectNode) additionalInfo).put(HOME_DASHBOARD_HIDE_TOOLBAR, homeDashboardInfo.isHideDashboardToolbar());
((ObjectNode) additionalInfo).put(HOME_DASHBOARD_HIDE_TOOLBAR, homeDashboardInfo.isHideDashboardToolbar()); } else {
} else { ((ObjectNode) additionalInfo).remove(HOME_DASHBOARD_ID);
((ObjectNode) additionalInfo).remove(HOME_DASHBOARD_ID); ((ObjectNode) additionalInfo).remove(HOME_DASHBOARD_HIDE_TOOLBAR);
((ObjectNode) additionalInfo).remove(HOME_DASHBOARD_HIDE_TOOLBAR);
}
tenant.setAdditionalInfo(additionalInfo);
tenantService.saveTenant(tenant);
} catch (Exception e) {
throw handleException(e);
} }
tenant.setAdditionalInfo(additionalInfo);
tenantService.saveTenant(tenant);
} }
private HomeDashboardInfo extractHomeDashboardInfoFromAdditionalInfo(JsonNode additionalInfo) { private HomeDashboardInfo extractHomeDashboardInfoFromAdditionalInfo(JsonNode additionalInfo) {
@ -681,28 +645,24 @@ public class DashboardController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("edgeId", strEdgeId); checkParameter("edgeId", strEdgeId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ);
checkEdgeId(edgeId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageData<DashboardInfo> nonFilteredResult = dashboardService.findDashboardsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
PageData<DashboardInfo> nonFilteredResult = dashboardService.findDashboardsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); List<DashboardInfo> filteredDashboards = nonFilteredResult.getData().stream().filter(dashboardInfo -> {
List<DashboardInfo> filteredDashboards = nonFilteredResult.getData().stream().filter(dashboardInfo -> { try {
try { accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, Operation.READ, dashboardInfo.getId(), dashboardInfo);
accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, Operation.READ, dashboardInfo.getId(), dashboardInfo); return true;
return true; } catch (ThingsboardException e) {
} catch (ThingsboardException e) { return false;
return false; }
} }).collect(Collectors.toList());
}).collect(Collectors.toList()); PageData<DashboardInfo> filteredResult = new PageData<>(filteredDashboards,
PageData<DashboardInfo> filteredResult = new PageData<>(filteredDashboards, nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalPages(), nonFilteredResult.getTotalElements(),
nonFilteredResult.getTotalElements(), nonFilteredResult.hasNext());
nonFilteredResult.hasNext()); return checkNotNull(filteredResult);
return checkNotNull(filteredResult);
} catch (Exception e) {
throw handleException(e);
}
} }
private Set<CustomerId> customerIdFromStr(String[] strCustomerIds) { private Set<CustomerId> customerIdFromStr(String[] strCustomerIds) {

225
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -77,6 +77,7 @@ import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH;
@ -308,16 +309,12 @@ public class DeviceController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(deviceService.findDevicesByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(deviceService.findDevicesByTenantIdAndType(tenantId, type, pageLink)); } else {
} else { return checkNotNull(deviceService.findDevicesByTenantId(tenantId, pageLink));
return checkNotNull(deviceService.findDevicesByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -343,19 +340,15 @@ public class DeviceController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder @RequestParam(required = false) String sortOrder
) throws ThingsboardException { ) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink)); } else if (deviceProfileId != null && deviceProfileId.length() > 0) {
} else if (deviceProfileId != null && deviceProfileId.length() > 0) { DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId));
DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId)); return checkNotNull(deviceService.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, profileId, pageLink));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, profileId, pageLink)); } else {
} else { return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink));
return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -368,12 +361,8 @@ public class DeviceController extends BaseController {
public Device getTenantDevice( public Device getTenantDevice(
@ApiParam(value = DEVICE_NAME_DESCRIPTION) @ApiParam(value = DEVICE_NAME_DESCRIPTION)
@RequestParam String deviceName) throws ThingsboardException { @RequestParam String deviceName) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(deviceService.findDeviceByTenantIdAndName(tenantId, deviceName));
return checkNotNull(deviceService.findDeviceByTenantIdAndName(tenantId, deviceName));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Customer Devices (getCustomerDevices)", @ApiOperation(value = "Get Customer Devices (getCustomerDevices)",
@ -398,18 +387,14 @@ public class DeviceController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); } else {
} else { return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -437,21 +422,17 @@ public class DeviceController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); } else if (deviceProfileId != null && deviceProfileId.length() > 0) {
} else if (deviceProfileId != null && deviceProfileId.length() > 0) { DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId));
DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId)); return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId, customerId, profileId, pageLink));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId, customerId, profileId, pageLink)); } else {
} else { return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -462,26 +443,22 @@ public class DeviceController extends BaseController {
@ResponseBody @ResponseBody
public List<Device> getDevicesByIds( public List<Device> getDevicesByIds(
@ApiParam(value = "A list of devices ids, separated by comma ','") @ApiParam(value = "A list of devices ids, separated by comma ','")
@RequestParam("deviceIds") String[] strDeviceIds) throws ThingsboardException { @RequestParam("deviceIds") String[] strDeviceIds) throws ThingsboardException, ExecutionException, InterruptedException {
checkArrayParameter("deviceIds", strDeviceIds); checkArrayParameter("deviceIds", strDeviceIds);
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); CustomerId customerId = user.getCustomerId();
CustomerId customerId = user.getCustomerId(); List<DeviceId> deviceIds = new ArrayList<>();
List<DeviceId> deviceIds = new ArrayList<>(); for (String strDeviceId : strDeviceIds) {
for (String strDeviceId : strDeviceIds) { deviceIds.add(new DeviceId(toUUID(strDeviceId)));
deviceIds.add(new DeviceId(toUUID(strDeviceId))); }
} ListenableFuture<List<Device>> devices;
ListenableFuture<List<Device>> devices; if (customerId == null || customerId.isNullUid()) {
if (customerId == null || customerId.isNullUid()) { devices = deviceService.findDevicesByTenantIdAndIdsAsync(tenantId, deviceIds);
devices = deviceService.findDevicesByTenantIdAndIdsAsync(tenantId, deviceIds); } else {
} else { devices = deviceService.findDevicesByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, deviceIds);
devices = deviceService.findDevicesByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, deviceIds);
}
return checkNotNull(devices.get());
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(devices.get());
} }
@ApiOperation(value = "Find related devices (findByQuery)", @ApiOperation(value = "Find related devices (findByQuery)",
@ -493,25 +470,21 @@ public class DeviceController extends BaseController {
@ResponseBody @ResponseBody
public List<Device> findByQuery( public List<Device> findByQuery(
@ApiParam(value = "The device search query JSON") @ApiParam(value = "The device search query JSON")
@RequestBody DeviceSearchQuery query) throws ThingsboardException { @RequestBody DeviceSearchQuery query) throws ThingsboardException, ExecutionException, InterruptedException {
checkNotNull(query); checkNotNull(query);
checkNotNull(query.getParameters()); checkNotNull(query.getParameters());
checkNotNull(query.getDeviceTypes()); checkNotNull(query.getDeviceTypes());
checkEntityId(query.getParameters().getEntityId(), Operation.READ); checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try { List<Device> devices = checkNotNull(deviceService.findDevicesByQuery(getCurrentUser().getTenantId(), query).get());
List<Device> devices = checkNotNull(deviceService.findDevicesByQuery(getCurrentUser().getTenantId(), query).get()); devices = devices.stream().filter(device -> {
devices = devices.stream().filter(device -> { try {
try { accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device);
accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device); return true;
return true; } catch (ThingsboardException e) {
} catch (ThingsboardException e) { return false;
return false; }
} }).collect(Collectors.toList());
}).collect(Collectors.toList()); return devices;
return devices;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Device Types (getDeviceTypes)", @ApiOperation(value = "Get Device Types (getDeviceTypes)",
@ -520,15 +493,11 @@ public class DeviceController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/types", method = RequestMethod.GET) @RequestMapping(value = "/device/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<EntitySubtype> getDeviceTypes() throws ThingsboardException { public List<EntitySubtype> getDeviceTypes() throws ThingsboardException, ExecutionException, InterruptedException {
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); ListenableFuture<List<EntitySubtype>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
ListenableFuture<List<EntitySubtype>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId); return checkNotNull(deviceTypes.get());
return checkNotNull(deviceTypes.get());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Claim device (claimDevice)", @ApiOperation(value = "Claim device (claimDevice)",
@ -722,33 +691,29 @@ public class DeviceController extends BaseController {
@ApiParam(value = "Timestamp. Devices with creation time after it won't be queried") @ApiParam(value = "Timestamp. Devices with creation time after it won't be queried")
@RequestParam(required = false) Long endTime) throws ThingsboardException { @RequestParam(required = false) Long endTime) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ);
checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); PageData<Device> nonFilteredResult;
PageData<Device> nonFilteredResult; if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { nonFilteredResult = deviceService.findDevicesByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink);
nonFilteredResult = deviceService.findDevicesByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink); } else {
} else { nonFilteredResult = deviceService.findDevicesByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
nonFilteredResult = deviceService.findDevicesByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
}
List<Device> filteredDevices = nonFilteredResult.getData().stream().filter(device -> {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device);
return true;
} catch (ThingsboardException e) {
return false;
}
}).collect(Collectors.toList());
PageData<Device> filteredResult = new PageData<>(filteredDevices,
nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalElements(),
nonFilteredResult.hasNext());
return checkNotNull(filteredResult);
} catch (Exception e) {
throw handleException(e);
} }
List<Device> filteredDevices = nonFilteredResult.getData().stream().filter(device -> {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device);
return true;
} catch (ThingsboardException e) {
return false;
}
}).collect(Collectors.toList());
PageData<Device> filteredResult = new PageData<>(filteredDevices,
nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalElements(),
nonFilteredResult.hasNext());
return checkNotNull(filteredResult);
} }
@ApiOperation(value = "Count devices by device profile (countByDeviceProfileAndEmptyOtaPackage)", @ApiOperation(value = "Count devices by device profile (countByDeviceProfileAndEmptyOtaPackage)",
@ -766,14 +731,10 @@ public class DeviceController extends BaseController {
@PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException {
checkParameter("OtaPackageType", otaPackageType); checkParameter("OtaPackageType", otaPackageType);
checkParameter("DeviceProfileId", deviceProfileId); checkParameter("DeviceProfileId", deviceProfileId);
try { return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(
return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage( getTenantId(),
getTenantId(), new DeviceProfileId(UUID.fromString(deviceProfileId)),
new DeviceProfileId(UUID.fromString(deviceProfileId)), OtaPackageType.valueOf(otaPackageType));
OtaPackageType.valueOf(otaPackageType));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Import the bulk of devices (processDevicesBulkImport)", @ApiOperation(value = "Import the bulk of devices (processDevicesBulkImport)",

50
application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java

@ -87,12 +87,8 @@ public class DeviceProfileController extends BaseController {
@ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException { @PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException {
checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId); checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId);
try { DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId));
DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId)); return checkDeviceProfileId(deviceProfileId, Operation.READ);
return checkDeviceProfileId(deviceProfileId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)", @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)",
@ -106,12 +102,8 @@ public class DeviceProfileController extends BaseController {
@ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException { @PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException {
checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId); checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId);
try { DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId));
DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId)); return new DeviceProfileInfo(checkDeviceProfileId(deviceProfileId, Operation.READ));
return new DeviceProfileInfo(checkDeviceProfileId(deviceProfileId, Operation.READ));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)", @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)",
@ -122,11 +114,7 @@ public class DeviceProfileController extends BaseController {
@RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET) @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public DeviceProfileInfo getDefaultDeviceProfileInfo() throws ThingsboardException { public DeviceProfileInfo getDefaultDeviceProfileInfo() throws ThingsboardException {
try { return checkNotNull(deviceProfileService.findDefaultDeviceProfileInfo(getTenantId()));
return checkNotNull(deviceProfileService.findDefaultDeviceProfileInfo(getTenantId()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get time-series keys (getTimeseriesKeys)", @ApiOperation(value = "Get time-series keys (getTimeseriesKeys)",
@ -150,11 +138,7 @@ public class DeviceProfileController extends BaseController {
deviceProfileId = null; deviceProfileId = null;
} }
try { return timeseriesService.findAllKeysByDeviceProfileId(getTenantId(), deviceProfileId);
return timeseriesService.findAllKeysByDeviceProfileId(getTenantId(), deviceProfileId);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get attribute keys (getAttributesKeys)", @ApiOperation(value = "Get attribute keys (getAttributesKeys)",
@ -178,11 +162,7 @@ public class DeviceProfileController extends BaseController {
deviceProfileId = null; deviceProfileId = null;
} }
try { return attributesService.findAllKeysByDeviceProfileId(getTenantId(), deviceProfileId);
return attributesService.findAllKeysByDeviceProfileId(getTenantId(), deviceProfileId);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Device Profile (saveDeviceProfile)", @ApiOperation(value = "Create Or Update Device Profile (saveDeviceProfile)",
@ -256,12 +236,8 @@ public class DeviceProfileController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(deviceProfileService.findDeviceProfiles(getTenantId(), pageLink));
return checkNotNull(deviceProfileService.findDeviceProfiles(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)", @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)",
@ -284,11 +260,7 @@ public class DeviceProfileController extends BaseController {
@RequestParam(required = false) String sortOrder, @RequestParam(required = false) String sortOrder,
@ApiParam(value = "Type of the transport", allowableValues = TRANSPORT_TYPE_ALLOWABLE_VALUES) @ApiParam(value = "Type of the transport", allowableValues = TRANSPORT_TYPE_ALLOWABLE_VALUES)
@RequestParam(required = false) String transportType) throws ThingsboardException { @RequestParam(required = false) String transportType) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(deviceProfileService.findDeviceProfileInfos(getTenantId(), pageLink, transportType));
return checkNotNull(deviceProfileService.findDeviceProfileInfos(getTenantId(), pageLink, transportType));
} catch (Exception e) {
throw handleException(e);
}
} }
} }

249
application/src/main/java/org/thingsboard/server/controller/EdgeController.java

@ -68,6 +68,7 @@ import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
@ -118,12 +119,8 @@ public class EdgeController extends BaseController {
public Edge getEdgeById(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) public Edge getEdgeById(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); return checkEdgeId(edgeId, Operation.READ);
return checkEdgeId(edgeId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Edge Info (getEdgeInfoById)", @ApiOperation(value = "Get Edge Info (getEdgeInfoById)",
@ -135,12 +132,8 @@ public class EdgeController extends BaseController {
public EdgeInfo getEdgeInfoById(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) public EdgeInfo getEdgeInfoById(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); return checkEdgeInfoId(edgeId, Operation.READ);
return checkEdgeInfoId(edgeId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Edge (saveEdge)", @ApiOperation(value = "Create Or Update Edge (saveEdge)",
@ -205,13 +198,9 @@ public class EdgeController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(edgeService.findEdgesByTenantId(tenantId, pageLink));
return checkNotNull(edgeService.findEdgesByTenantId(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)", @ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)",
@ -287,16 +276,12 @@ public class EdgeController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(edgeService.findEdgesByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(edgeService.findEdgesByTenantIdAndType(tenantId, type, pageLink)); } else {
} else { return checkNotNull(edgeService.findEdgesByTenantId(tenantId, pageLink));
return checkNotNull(edgeService.findEdgesByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -320,16 +305,12 @@ public class EdgeController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(edgeService.findEdgeInfosByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(edgeService.findEdgeInfosByTenantIdAndType(tenantId, type, pageLink)); } else {
} else { return checkNotNull(edgeService.findEdgeInfosByTenantId(tenantId, pageLink));
return checkNotNull(edgeService.findEdgeInfosByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -342,12 +323,8 @@ public class EdgeController extends BaseController {
@ResponseBody @ResponseBody
public Edge getTenantEdge(@ApiParam(value = "Unique name of the edge", required = true) public Edge getTenantEdge(@ApiParam(value = "Unique name of the edge", required = true)
@RequestParam String edgeName) throws ThingsboardException { @RequestParam String edgeName) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(edgeService.findEdgeByTenantIdAndName(tenantId, edgeName));
return checkNotNull(edgeService.findEdgeByTenantIdAndName(tenantId, edgeName));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Set root rule chain for provided edge (setEdgeRootRuleChain)", @ApiOperation(value = "Set root rule chain for provided edge (setEdgeRootRuleChain)",
@ -393,22 +370,18 @@ public class EdgeController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageData<Edge> result;
PageData<Edge> result; if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { result = edgeService.findEdgesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink);
result = edgeService.findEdgesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink); } else {
} else { result = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink);
result = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink);
}
return checkNotNull(result);
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(result);
} }
@ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)", @ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)",
@ -433,22 +406,18 @@ public class EdgeController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageData<EdgeInfo> result;
PageData<EdgeInfo> result; if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { result = edgeService.findEdgeInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink);
result = edgeService.findEdgeInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink); } else {
} else { result = edgeService.findEdgeInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink);
result = edgeService.findEdgeInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink);
}
return checkNotNull(result);
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(result);
} }
@ApiOperation(value = "Get Edges By Ids (getEdgesByIds)", @ApiOperation(value = "Get Edges By Ids (getEdgesByIds)",
@ -459,27 +428,23 @@ public class EdgeController extends BaseController {
@ResponseBody @ResponseBody
public List<Edge> getEdgesByIds( public List<Edge> getEdgesByIds(
@ApiParam(value = "A list of edges ids, separated by comma ','", required = true) @ApiParam(value = "A list of edges ids, separated by comma ','", required = true)
@RequestParam("edgeIds") String[] strEdgeIds) throws ThingsboardException { @RequestParam("edgeIds") String[] strEdgeIds) throws ThingsboardException, ExecutionException, InterruptedException {
checkArrayParameter("edgeIds", strEdgeIds); checkArrayParameter("edgeIds", strEdgeIds);
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); CustomerId customerId = user.getCustomerId();
CustomerId customerId = user.getCustomerId(); List<EdgeId> edgeIds = new ArrayList<>();
List<EdgeId> edgeIds = new ArrayList<>(); for (String strEdgeId : strEdgeIds) {
for (String strEdgeId : strEdgeIds) { edgeIds.add(new EdgeId(toUUID(strEdgeId)));
edgeIds.add(new EdgeId(toUUID(strEdgeId))); }
} ListenableFuture<List<Edge>> edgesFuture;
ListenableFuture<List<Edge>> edgesFuture; if (customerId == null || customerId.isNullUid()) {
if (customerId == null || customerId.isNullUid()) { edgesFuture = edgeService.findEdgesByTenantIdAndIdsAsync(tenantId, edgeIds);
edgesFuture = edgeService.findEdgesByTenantIdAndIdsAsync(tenantId, edgeIds); } else {
} else { edgesFuture = edgeService.findEdgesByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, edgeIds);
edgesFuture = edgeService.findEdgesByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, edgeIds);
}
List<Edge> edges = edgesFuture.get();
return checkNotNull(edges);
} catch (Exception e) {
throw handleException(e);
} }
List<Edge> edges = edgesFuture.get();
return checkNotNull(edges);
} }
@ApiOperation(value = "Find related edges (findByQuery)", @ApiOperation(value = "Find related edges (findByQuery)",
@ -490,27 +455,23 @@ public class EdgeController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edges", method = RequestMethod.POST) @RequestMapping(value = "/edges", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public List<Edge> findByQuery(@RequestBody EdgeSearchQuery query) throws ThingsboardException { public List<Edge> findByQuery(@RequestBody EdgeSearchQuery query) throws ThingsboardException, ExecutionException, InterruptedException {
checkNotNull(query); checkNotNull(query);
checkNotNull(query.getParameters()); checkNotNull(query.getParameters());
checkNotNull(query.getEdgeTypes()); checkNotNull(query.getEdgeTypes());
checkEntityId(query.getParameters().getEntityId(), Operation.READ); checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); List<Edge> edges = checkNotNull(edgeService.findEdgesByQuery(tenantId, query).get());
List<Edge> edges = checkNotNull(edgeService.findEdgesByQuery(tenantId, query).get()); edges = edges.stream().filter(edge -> {
edges = edges.stream().filter(edge -> { try {
try { accessControlService.checkPermission(user, Resource.EDGE, Operation.READ, edge.getId(), edge);
accessControlService.checkPermission(user, Resource.EDGE, Operation.READ, edge.getId(), edge); return true;
return true; } catch (ThingsboardException e) {
} catch (ThingsboardException e) { return false;
return false; }
} }).collect(Collectors.toList());
}).collect(Collectors.toList()); return edges;
return edges;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Edge Types (getEdgeTypes)", @ApiOperation(value = "Get Edge Types (getEdgeTypes)",
@ -520,15 +481,11 @@ public class EdgeController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/types", method = RequestMethod.GET) @RequestMapping(value = "/edge/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<EntitySubtype> getEdgeTypes() throws ThingsboardException { public List<EntitySubtype> getEdgeTypes() throws ThingsboardException, ExecutionException, InterruptedException {
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); ListenableFuture<List<EntitySubtype>> edgeTypes = edgeService.findEdgeTypesByTenantId(tenantId);
ListenableFuture<List<EntitySubtype>> edgeTypes = edgeService.findEdgeTypesByTenantId(tenantId); return checkNotNull(edgeTypes.get());
return checkNotNull(edgeTypes.get());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Sync edge (syncEdge)", @ApiOperation(value = "Sync edge (syncEdge)",
@ -539,22 +496,18 @@ public class EdgeController extends BaseController {
public DeferredResult<ResponseEntity> syncEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) public DeferredResult<ResponseEntity> syncEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("edgeId") String strEdgeId) throws ThingsboardException { @PathVariable("edgeId") String strEdgeId) throws ThingsboardException {
checkParameter("edgeId", strEdgeId); checkParameter("edgeId", strEdgeId);
try { final DeferredResult<ResponseEntity> response = new DeferredResult<>();
final DeferredResult<ResponseEntity> response = new DeferredResult<>(); if (isEdgesEnabled()) {
if (isEdgesEnabled()) { EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); edgeId = checkNotNull(edgeId);
edgeId = checkNotNull(edgeId); SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); ToEdgeSyncRequest request = new ToEdgeSyncRequest(UUID.randomUUID(), tenantId, edgeId);
ToEdgeSyncRequest request = new ToEdgeSyncRequest(UUID.randomUUID(), tenantId, edgeId); edgeRpcService.processSyncRequest(request, fromEdgeSyncResponse -> reply(response, fromEdgeSyncResponse));
edgeRpcService.processSyncRequest(request, fromEdgeSyncResponse -> reply(response, fromEdgeSyncResponse)); } else {
} else { throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL);
throw new ThingsboardException("Edges support disabled", ThingsboardErrorCode.GENERAL);
}
return response;
} catch (Exception e) {
throw handleException(e);
} }
return response;
} }
private void reply(DeferredResult<ResponseEntity> response, FromEdgeSyncResponse fromEdgeSyncResponse) { private void reply(DeferredResult<ResponseEntity> response, FromEdgeSyncResponse fromEdgeSyncResponse) {
@ -572,15 +525,11 @@ public class EdgeController extends BaseController {
@ResponseBody @ResponseBody
public String findMissingToRelatedRuleChains(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) public String findMissingToRelatedRuleChains(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("edgeId") String strEdgeId) throws ThingsboardException { @PathVariable("edgeId") String strEdgeId) throws ThingsboardException {
try { EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); edgeId = checkNotNull(edgeId);
edgeId = checkNotNull(edgeId); SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); return edgeService.findMissingToRelatedRuleChains(tenantId, edgeId, TbRuleChainInputNode.class.getName());
return edgeService.findMissingToRelatedRuleChains(tenantId, edgeId, TbRuleChainInputNode.class.getName());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)", @ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)",
@ -608,13 +557,9 @@ public class EdgeController extends BaseController {
@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("edgeId") String strEdgeId, @PathVariable("edgeId") String strEdgeId,
HttpServletRequest request) throws ThingsboardException { HttpServletRequest request) throws ThingsboardException {
try { EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); edgeId = checkNotNull(edgeId);
edgeId = checkNotNull(edgeId); Edge edge = checkEdgeId(edgeId, Operation.READ);
Edge edge = checkEdgeId(edgeId, Operation.READ); return checkNotNull(edgeInstallService.getDockerInstallInstructions(getTenantId(), edge, request));
return checkNotNull(edgeInstallService.getDockerInstallInstructions(getTenantId(), edge, request));
} catch (Exception e) {
throw handleException(e);
}
} }
} }

14
application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java

@ -81,14 +81,10 @@ public class EdgeEventController extends BaseController {
@ApiParam(value = "Timestamp. Edge events with creation time after it won't be queried") @ApiParam(value = "Timestamp. Edge events with creation time after it won't be queried")
@RequestParam(required = false) Long endTime) throws ThingsboardException { @RequestParam(required = false) Long endTime) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ);
checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, false));
return checkNotNull(edgeEventService.findEdgeEvents(tenantId, edgeId, pageLink, false));
} catch (Exception e) {
throw handleException(e);
}
} }
} }

83
application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java

@ -41,6 +41,7 @@ import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION;
@ -143,21 +144,17 @@ public class EntityRelationController extends BaseController {
@ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup,
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId,
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType) throws ThingsboardException { @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType) throws ThingsboardException {
try { checkParameter(FROM_ID, strFromId);
checkParameter(FROM_ID, strFromId); checkParameter(FROM_TYPE, strFromType);
checkParameter(FROM_TYPE, strFromType); checkParameter(RELATION_TYPE, strRelationType);
checkParameter(RELATION_TYPE, strRelationType); checkParameter(TO_ID, strToId);
checkParameter(TO_ID, strToId); checkParameter(TO_TYPE, strToType);
checkParameter(TO_TYPE, strToType); EntityId fromId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
EntityId fromId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId);
EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId); checkEntityId(fromId, Operation.READ);
checkEntityId(fromId, Operation.READ); checkEntityId(toId, Operation.READ);
checkEntityId(toId, Operation.READ); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); return checkNotNull(relationService.getRelation(getTenantId(), fromId, toId, strRelationType, typeGroup));
return checkNotNull(relationService.getRelation(getTenantId(), fromId, toId, strRelationType, typeGroup));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get List of Relations (findByFrom)", @ApiOperation(value = "Get List of Relations (findByFrom)",
@ -176,11 +173,7 @@ public class EntityRelationController extends BaseController {
EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findByFrom(getTenantId(), entityId, typeGroup)));
return checkNotNull(filterRelationsByReadPermission(relationService.findByFrom(getTenantId(), entityId, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get List of Relation Infos (findInfoByFrom)", @ApiOperation(value = "Get List of Relation Infos (findInfoByFrom)",
@ -193,17 +186,13 @@ public class EntityRelationController extends BaseController {
public List<EntityRelationInfo> findInfoByFrom(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, public List<EntityRelationInfo> findInfoByFrom(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId,
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType,
@ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION)
@RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException, ExecutionException, InterruptedException {
checkParameter(FROM_ID, strFromId); checkParameter(FROM_ID, strFromId);
checkParameter(FROM_TYPE, strFromType); checkParameter(FROM_TYPE, strFromType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByFrom(getTenantId(), entityId, typeGroup).get()));
return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByFrom(getTenantId(), entityId, typeGroup).get()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get List of Relations (findByFrom)", @ApiOperation(value = "Get List of Relations (findByFrom)",
@ -224,11 +213,7 @@ public class EntityRelationController extends BaseController {
EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId); EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findByFromAndType(getTenantId(), entityId, strRelationType, typeGroup)));
return checkNotNull(filterRelationsByReadPermission(relationService.findByFromAndType(getTenantId(), entityId, strRelationType, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get List of Relations (findByTo)", @ApiOperation(value = "Get List of Relations (findByTo)",
@ -247,11 +232,7 @@ public class EntityRelationController extends BaseController {
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findByTo(getTenantId(), entityId, typeGroup)));
return checkNotNull(filterRelationsByReadPermission(relationService.findByTo(getTenantId(), entityId, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get List of Relation Infos (findInfoByTo)", @ApiOperation(value = "Get List of Relation Infos (findInfoByTo)",
@ -264,17 +245,13 @@ public class EntityRelationController extends BaseController {
public List<EntityRelationInfo> findInfoByTo(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, public List<EntityRelationInfo> findInfoByTo(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId,
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType,
@ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION)
@RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException, ExecutionException, InterruptedException {
checkParameter(TO_ID, strToId); checkParameter(TO_ID, strToId);
checkParameter(TO_TYPE, strToType); checkParameter(TO_TYPE, strToType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByTo(getTenantId(), entityId, typeGroup).get()));
return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByTo(getTenantId(), entityId, typeGroup).get()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get List of Relations (findByTo)", @ApiOperation(value = "Get List of Relations (findByTo)",
@ -295,11 +272,7 @@ public class EntityRelationController extends BaseController {
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(entityId, Operation.READ); checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findByToAndType(getTenantId(), entityId, strRelationType, typeGroup)));
return checkNotNull(filterRelationsByReadPermission(relationService.findByToAndType(getTenantId(), entityId, strRelationType, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Find related entities (findByQuery)", @ApiOperation(value = "Find related entities (findByQuery)",
@ -310,16 +283,12 @@ public class EntityRelationController extends BaseController {
@RequestMapping(value = "/relations", method = RequestMethod.POST) @RequestMapping(value = "/relations", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public List<EntityRelation> findByQuery(@ApiParam(value = "A JSON value representing the entity relations query object.", required = true) public List<EntityRelation> findByQuery(@ApiParam(value = "A JSON value representing the entity relations query object.", required = true)
@RequestBody EntityRelationsQuery query) throws ThingsboardException { @RequestBody EntityRelationsQuery query) throws ThingsboardException, ExecutionException, InterruptedException {
checkNotNull(query); checkNotNull(query);
checkNotNull(query.getParameters()); checkNotNull(query.getParameters());
checkNotNull(query.getFilters()); checkNotNull(query.getFilters());
checkEntityId(query.getParameters().getEntityId(), Operation.READ); checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findByQuery(getTenantId(), query).get()));
return checkNotNull(filterRelationsByReadPermission(relationService.findByQuery(getTenantId(), query).get()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Find related entity infos (findInfoByQuery)", @ApiOperation(value = "Find related entity infos (findInfoByQuery)",
@ -330,16 +299,12 @@ public class EntityRelationController extends BaseController {
@RequestMapping(value = "/relations/info", method = RequestMethod.POST) @RequestMapping(value = "/relations/info", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public List<EntityRelationInfo> findInfoByQuery(@ApiParam(value = "A JSON value representing the entity relations query object.", required = true) public List<EntityRelationInfo> findInfoByQuery(@ApiParam(value = "A JSON value representing the entity relations query object.", required = true)
@RequestBody EntityRelationsQuery query) throws ThingsboardException { @RequestBody EntityRelationsQuery query) throws ThingsboardException, ExecutionException, InterruptedException {
checkNotNull(query); checkNotNull(query);
checkNotNull(query.getParameters()); checkNotNull(query.getParameters());
checkNotNull(query.getFilters()); checkNotNull(query.getFilters());
checkEntityId(query.getParameters().getEntityId(), Operation.READ); checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try { return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByQuery(getTenantId(), query).get()));
return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByQuery(getTenantId(), query).get()));
} catch (Exception e) {
throw handleException(e);
}
} }
private void checkCanCreateRelation(EntityId entityId) throws ThingsboardException { private void checkCanCreateRelation(EntityId entityId) throws ThingsboardException {

185
application/src/main/java/org/thingsboard/server/controller/EntityViewController.java

@ -54,6 +54,7 @@ import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID;
@ -105,11 +106,7 @@ public class EntityViewController extends BaseController {
@ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
checkParameter(ENTITY_VIEW_ID, strEntityViewId); checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try { return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ);
return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Entity View info (getEntityViewInfoById)", @ApiOperation(value = "Get Entity View info (getEntityViewInfoById)",
@ -123,12 +120,8 @@ public class EntityViewController extends BaseController {
@ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
checkParameter(ENTITY_VIEW_ID, strEntityViewId); checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try { EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); return checkEntityViewInfoId(entityViewId, Operation.READ);
return checkEntityViewInfoId(entityViewId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Save or update entity view (saveEntityView)", @ApiOperation(value = "Save or update entity view (saveEntityView)",
@ -177,12 +170,8 @@ public class EntityViewController extends BaseController {
public EntityView getTenantEntityView( public EntityView getTenantEntityView(
@ApiParam(value = "Entity View name") @ApiParam(value = "Entity View name")
@RequestParam String entityViewName) throws ThingsboardException { @RequestParam String entityViewName) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(entityViewService.findEntityViewByTenantIdAndName(tenantId, entityViewName));
return checkNotNull(entityViewService.findEntityViewByTenantIdAndName(tenantId, entityViewName));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Assign Entity View to customer (assignEntityViewToCustomer)", @ApiOperation(value = "Assign Entity View to customer (assignEntityViewToCustomer)",
@ -249,18 +238,14 @@ public class EntityViewController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(CUSTOMER_ID, strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type));
return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type)); } else {
} else { return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -286,18 +271,14 @@ public class EntityViewController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); } else {
} else { return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -320,17 +301,13 @@ public class EntityViewController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type));
return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type)); } else {
} else { return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink));
return checkNotNull(entityViewService.findEntityViewByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -353,16 +330,12 @@ public class EntityViewController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndType(tenantId, type, pageLink));
return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndType(tenantId, type, pageLink)); } else {
} else { return checkNotNull(entityViewService.findEntityViewInfosByTenantId(tenantId, pageLink));
return checkNotNull(entityViewService.findEntityViewInfosByTenantId(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -375,25 +348,21 @@ public class EntityViewController extends BaseController {
@ResponseBody @ResponseBody
public List<EntityView> findByQuery( public List<EntityView> findByQuery(
@ApiParam(value = "The entity view search query JSON") @ApiParam(value = "The entity view search query JSON")
@RequestBody EntityViewSearchQuery query) throws ThingsboardException { @RequestBody EntityViewSearchQuery query) throws ThingsboardException, ExecutionException, InterruptedException {
checkNotNull(query); checkNotNull(query);
checkNotNull(query.getParameters()); checkNotNull(query.getParameters());
checkNotNull(query.getEntityViewTypes()); checkNotNull(query.getEntityViewTypes());
checkEntityId(query.getParameters().getEntityId(), Operation.READ); checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try { List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(getTenantId(), query).get());
List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(getTenantId(), query).get()); entityViews = entityViews.stream().filter(entityView -> {
entityViews = entityViews.stream().filter(entityView -> { try {
try { accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView);
accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView); return true;
return true; } catch (ThingsboardException e) {
} catch (ThingsboardException e) { return false;
return false; }
} }).collect(Collectors.toList());
}).collect(Collectors.toList()); return entityViews;
return entityViews;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Entity View Types (getEntityViewTypes)", @ApiOperation(value = "Get Entity View Types (getEntityViewTypes)",
@ -402,15 +371,11 @@ public class EntityViewController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/entityView/types", method = RequestMethod.GET) @RequestMapping(value = "/entityView/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<EntitySubtype> getEntityViewTypes() throws ThingsboardException { public List<EntitySubtype> getEntityViewTypes() throws ThingsboardException, ExecutionException, InterruptedException {
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId();
TenantId tenantId = user.getTenantId(); ListenableFuture<List<EntitySubtype>> entityViewTypes = entityViewService.findEntityViewTypesByTenantId(tenantId);
ListenableFuture<List<EntitySubtype>> entityViewTypes = entityViewService.findEntityViewTypesByTenantId(tenantId); return checkNotNull(entityViewTypes.get());
return checkNotNull(entityViewTypes.get());
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Make entity view publicly available (assignEntityViewToPublicCustomer)", @ApiOperation(value = "Make entity view publicly available (assignEntityViewToPublicCustomer)",
@ -493,32 +458,28 @@ public class EntityViewController extends BaseController {
@RequestParam(required = false) Long startTime, @RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime) throws ThingsboardException { @RequestParam(required = false) Long endTime) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ);
checkEdgeId(edgeId, Operation.READ); TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime);
TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); PageData<EntityView> nonFilteredResult;
PageData<EntityView> nonFilteredResult; if (type != null && type.trim().length() > 0) {
if (type != null && type.trim().length() > 0) { nonFilteredResult = entityViewService.findEntityViewsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink);
nonFilteredResult = entityViewService.findEntityViewsByTenantIdAndEdgeIdAndType(tenantId, edgeId, type, pageLink); } else {
} else { nonFilteredResult = entityViewService.findEntityViewsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
nonFilteredResult = entityViewService.findEntityViewsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
}
List<EntityView> filteredEntityViews = nonFilteredResult.getData().stream().filter(entityView -> {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView);
return true;
} catch (ThingsboardException e) {
return false;
}
}).collect(Collectors.toList());
PageData<EntityView> filteredResult = new PageData<>(filteredEntityViews,
nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalElements(),
nonFilteredResult.hasNext());
return checkNotNull(filteredResult);
} catch (Exception e) {
throw handleException(e);
} }
List<EntityView> filteredEntityViews = nonFilteredResult.getData().stream().filter(entityView -> {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView);
return true;
} catch (ThingsboardException e) {
return false;
}
}).collect(Collectors.toList());
PageData<EntityView> filteredResult = new PageData<>(filteredEntityViews,
nonFilteredResult.getTotalPages(),
nonFilteredResult.getTotalElements(),
nonFilteredResult.hasNext());
return checkNotNull(filteredResult);
} }
} }

10
application/src/main/java/org/thingsboard/server/controller/EventController.java

@ -248,14 +248,10 @@ public class EventController extends BaseController {
@RequestBody EventFilter eventFilter) throws ThingsboardException { @RequestBody EventFilter eventFilter) throws ThingsboardException {
checkParameter("EntityId", strEntityId); checkParameter("EntityId", strEntityId);
checkParameter("EntityType", strEntityType); checkParameter("EntityType", strEntityType);
try { EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); checkEntityId(entityId, Operation.WRITE);
checkEntityId(entityId, Operation.WRITE);
eventService.removeEvents(getTenantId(), entityId, eventFilter, startTime, endTime); eventService.removeEvents(getTenantId(), entityId, eventFilter, startTime, endTime);
} catch (Exception e) {
throw handleException(e);
}
} }
private static EventType resolveEventType(String eventType) throws ThingsboardException { private static EventType resolveEventType(String eventType) throws ThingsboardException {

6
application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java

@ -64,11 +64,7 @@ public class Lwm2mController extends BaseController {
public LwM2MServerSecurityConfigDefault getLwm2mBootstrapSecurityInfo( public LwM2MServerSecurityConfigDefault getLwm2mBootstrapSecurityInfo(
@ApiParam(value = IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION) @ApiParam(value = IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION)
@PathVariable(IS_BOOTSTRAP_SERVER) boolean bootstrapServer) throws ThingsboardException { @PathVariable(IS_BOOTSTRAP_SERVER) boolean bootstrapServer) throws ThingsboardException {
try { return lwM2MService.getServerSecurityInfo(bootstrapServer);
return lwM2MService.getServerSecurityInfo(bootstrapServer);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(hidden = true, value = "Save device with credentials (Deprecated)") @ApiOperation(hidden = true, value = "Save device with credentials (Deprecated)")

26
application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.java

@ -54,12 +54,8 @@ public class OAuth2ConfigTemplateController extends BaseController {
@RequestMapping(method = RequestMethod.POST) @RequestMapping(method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public OAuth2ClientRegistrationTemplate saveClientRegistrationTemplate(@RequestBody OAuth2ClientRegistrationTemplate clientRegistrationTemplate) throws ThingsboardException { public OAuth2ClientRegistrationTemplate saveClientRegistrationTemplate(@RequestBody OAuth2ClientRegistrationTemplate clientRegistrationTemplate) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.WRITE);
accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.WRITE); return oAuth2ConfigTemplateService.saveClientRegistrationTemplate(clientRegistrationTemplate);
return oAuth2ConfigTemplateService.saveClientRegistrationTemplate(clientRegistrationTemplate);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Delete OAuth2 client registration template by id (deleteClientRegistrationTemplate)" + SYSTEM_AUTHORITY_PARAGRAPH, @ApiOperation(value = "Delete OAuth2 client registration template by id (deleteClientRegistrationTemplate)" + SYSTEM_AUTHORITY_PARAGRAPH,
@ -70,13 +66,9 @@ public class OAuth2ConfigTemplateController extends BaseController {
public void deleteClientRegistrationTemplate(@ApiParam(value = "String representation of client registration template id to delete", example = "139b1f81-2f5d-11ec-9dbe-9b627e1a88f4") public void deleteClientRegistrationTemplate(@ApiParam(value = "String representation of client registration template id to delete", example = "139b1f81-2f5d-11ec-9dbe-9b627e1a88f4")
@PathVariable(CLIENT_REGISTRATION_TEMPLATE_ID) String strClientRegistrationTemplateId) throws ThingsboardException { @PathVariable(CLIENT_REGISTRATION_TEMPLATE_ID) String strClientRegistrationTemplateId) throws ThingsboardException {
checkParameter(CLIENT_REGISTRATION_TEMPLATE_ID, strClientRegistrationTemplateId); checkParameter(CLIENT_REGISTRATION_TEMPLATE_ID, strClientRegistrationTemplateId);
try { accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.DELETE);
accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.DELETE); OAuth2ClientRegistrationTemplateId clientRegistrationTemplateId = new OAuth2ClientRegistrationTemplateId(toUUID(strClientRegistrationTemplateId));
OAuth2ClientRegistrationTemplateId clientRegistrationTemplateId = new OAuth2ClientRegistrationTemplateId(toUUID(strClientRegistrationTemplateId)); oAuth2ConfigTemplateService.deleteClientRegistrationTemplateById(clientRegistrationTemplateId);
oAuth2ConfigTemplateService.deleteClientRegistrationTemplateById(clientRegistrationTemplateId);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get the list of all OAuth2 client registration templates (getClientRegistrationTemplates)" + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, @ApiOperation(value = "Get the list of all OAuth2 client registration templates (getClientRegistrationTemplates)" + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH,
@ -85,12 +77,8 @@ public class OAuth2ConfigTemplateController extends BaseController {
@RequestMapping(method = RequestMethod.GET, produces = "application/json") @RequestMapping(method = RequestMethod.GET, produces = "application/json")
@ResponseBody @ResponseBody
public List<OAuth2ClientRegistrationTemplate> getClientRegistrationTemplates() throws ThingsboardException { public List<OAuth2ClientRegistrationTemplate> getClientRegistrationTemplates() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.READ); return oAuth2ConfigTemplateService.findAllClientRegistrationTemplates();
return oAuth2ConfigTemplateService.findAllClientRegistrationTemplates();
} catch (Exception e) {
throw handleException(e);
}
} }
} }

56
application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java

@ -69,25 +69,21 @@ public class OAuth2Controller extends BaseController {
"If platform type is not one of allowable values - it will just be ignored", "If platform type is not one of allowable values - it will just be ignored",
allowableValues = "WEB, ANDROID, IOS") allowableValues = "WEB, ANDROID, IOS")
@RequestParam(required = false) String platform) throws ThingsboardException { @RequestParam(required = false) String platform) throws ThingsboardException {
try { if (log.isDebugEnabled()) {
if (log.isDebugEnabled()) { log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort());
log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort()); Enumeration<String> headerNames = request.getHeaderNames();
Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) {
while (headerNames.hasMoreElements()) { String header = headerNames.nextElement();
String header = headerNames.nextElement(); log.debug("Header: {} {}", header, request.getHeader(header));
log.debug("Header: {} {}", header, request.getHeader(header));
}
} }
PlatformType platformType = null;
if (StringUtils.isNotEmpty(platform)) {
try {
platformType = PlatformType.valueOf(platform);
} catch (Exception e) {}
}
return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName, platformType);
} catch (Exception e) {
throw handleException(e);
} }
PlatformType platformType = null;
if (StringUtils.isNotEmpty(platform)) {
try {
platformType = PlatformType.valueOf(platform);
} catch (Exception e) {}
}
return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName, platformType);
} }
@ApiOperation(value = "Get current OAuth2 settings (getCurrentOAuth2Info)", notes = SYSTEM_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Get current OAuth2 settings (getCurrentOAuth2Info)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@ -95,12 +91,8 @@ public class OAuth2Controller extends BaseController {
@RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json") @RequestMapping(value = "/oauth2/config", method = RequestMethod.GET, produces = "application/json")
@ResponseBody @ResponseBody
public OAuth2Info getCurrentOAuth2Info() throws ThingsboardException { public OAuth2Info getCurrentOAuth2Info() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ); return oAuth2Service.findOAuth2Info();
return oAuth2Service.findOAuth2Info();
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Save OAuth2 settings (saveOAuth2Info)", notes = SYSTEM_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Save OAuth2 settings (saveOAuth2Info)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@ -108,13 +100,9 @@ public class OAuth2Controller extends BaseController {
@RequestMapping(value = "/oauth2/config", method = RequestMethod.POST) @RequestMapping(value = "/oauth2/config", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public OAuth2Info saveOAuth2Info(@RequestBody OAuth2Info oauth2Info) throws ThingsboardException { public OAuth2Info saveOAuth2Info(@RequestBody OAuth2Info oauth2Info) throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.WRITE);
accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.WRITE); oAuth2Service.saveOAuth2Info(oauth2Info);
oAuth2Service.saveOAuth2Info(oauth2Info); return oAuth2Service.findOAuth2Info();
return oAuth2Service.findOAuth2Info();
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get OAuth2 log in processing URL (getLoginProcessingUrl)", notes = "Returns the URL enclosed in " + @ApiOperation(value = "Get OAuth2 log in processing URL (getLoginProcessingUrl)", notes = "Returns the URL enclosed in " +
@ -125,12 +113,8 @@ public class OAuth2Controller extends BaseController {
@RequestMapping(value = "/oauth2/loginProcessingUrl", method = RequestMethod.GET) @RequestMapping(value = "/oauth2/loginProcessingUrl", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public String getLoginProcessingUrl() throws ThingsboardException { public String getLoginProcessingUrl() throws ThingsboardException {
try { accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ);
accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_INFO, Operation.READ); return "\"" + oAuth2Configuration.getLoginProcessingUrl() + "\"";
return "\"" + oAuth2Configuration.getLoginProcessingUrl() + "\"";
} catch (Exception e) {
throw handleException(e);
}
} }
} }

62
application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java

@ -87,24 +87,20 @@ public class OtaPackageController extends BaseController {
public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) public ResponseEntity<org.springframework.core.io.Resource> downloadOtaPackage(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try { OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); OtaPackage otaPackage = checkOtaPackageId(otaPackageId, Operation.READ);
OtaPackage otaPackage = checkOtaPackageId(otaPackageId, Operation.READ);
if (otaPackage.hasUrl()) {
return ResponseEntity.badRequest().build();
}
ByteArrayResource resource = new ByteArrayResource(otaPackage.getData().array()); if (otaPackage.hasUrl()) {
return ResponseEntity.ok() return ResponseEntity.badRequest().build();
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackage.getFileName())
.header("x-filename", otaPackage.getFileName())
.contentLength(resource.contentLength())
.contentType(parseMediaType(otaPackage.getContentType()))
.body(resource);
} catch (Exception e) {
throw handleException(e);
} }
ByteArrayResource resource = new ByteArrayResource(otaPackage.getData().array());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + otaPackage.getFileName())
.header("x-filename", otaPackage.getFileName())
.contentLength(resource.contentLength())
.contentType(parseMediaType(otaPackage.getContentType()))
.body(resource);
} }
@ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)", @ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)",
@ -117,12 +113,8 @@ public class OtaPackageController extends BaseController {
public OtaPackageInfo getOtaPackageInfoById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) public OtaPackageInfo getOtaPackageInfoById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try { OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); return checkNotNull(otaPackageService.findOtaPackageInfoById(getTenantId(), otaPackageId));
return checkNotNull(otaPackageService.findOtaPackageInfoById(getTenantId(), otaPackageId));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get OTA Package (getOtaPackageById)", @ApiOperation(value = "Get OTA Package (getOtaPackageById)",
@ -135,12 +127,8 @@ public class OtaPackageController extends BaseController {
public OtaPackage getOtaPackageById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) public OtaPackage getOtaPackageById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION)
@PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException {
checkParameter(OTA_PACKAGE_ID, strOtaPackageId); checkParameter(OTA_PACKAGE_ID, strOtaPackageId);
try { OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId));
OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); return checkOtaPackageId(otaPackageId, Operation.READ);
return checkOtaPackageId(otaPackageId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update OTA Package Info (saveOtaPackageInfo)", @ApiOperation(value = "Create Or Update OTA Package Info (saveOtaPackageInfo)",
@ -204,12 +192,8 @@ public class OtaPackageController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink));
return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)",
@ -235,13 +219,9 @@ public class OtaPackageController extends BaseController {
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("deviceProfileId", strDeviceProfileId); checkParameter("deviceProfileId", strDeviceProfileId);
checkParameter("type", strType); checkParameter("type", strType);
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(),
return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantIdAndDeviceProfileIdAndTypeAndHasData(getTenantId(), new DeviceProfileId(toUUID(strDeviceProfileId)), OtaPackageType.valueOf(strType), pageLink));
new DeviceProfileId(toUUID(strDeviceProfileId)), OtaPackageType.valueOf(strType), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Delete OTA Package (deleteOtaPackage)", @ApiOperation(value = "Delete OTA Package (deleteOtaPackage)",

100
application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java

@ -159,12 +159,8 @@ public class RpcV2Controller extends AbstractRpcController {
@ApiParam(value = RPC_ID_PARAM_DESCRIPTION, required = true) @ApiParam(value = RPC_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(RPC_ID) String strRpc) throws ThingsboardException { @PathVariable(RPC_ID) String strRpc) throws ThingsboardException {
checkParameter("RpcId", strRpc); checkParameter("RpcId", strRpc);
try { RpcId rpcId = new RpcId(UUID.fromString(strRpc));
RpcId rpcId = new RpcId(UUID.fromString(strRpc)); return checkRpcId(rpcId, Operation.READ);
return checkRpcId(rpcId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@ -187,43 +183,39 @@ public class RpcV2Controller extends AbstractRpcController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("DeviceId", strDeviceId); checkParameter("DeviceId", strDeviceId);
try { if (rpcStatus != null && rpcStatus.equals(RpcStatus.DELETED)) {
if (rpcStatus != null && rpcStatus.equals(RpcStatus.DELETED)) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "RpcStatus: DELETED");
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "RpcStatus: DELETED"); }
}
TenantId tenantId = getCurrentUser().getTenantId();
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
DeviceId deviceId = new DeviceId(UUID.fromString(strDeviceId));
final DeferredResult<ResponseEntity> response = new DeferredResult<>();
accessValidator.validate(getCurrentUser(), Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<>() { TenantId tenantId = getCurrentUser().getTenantId();
@Override PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) { DeviceId deviceId = new DeviceId(UUID.fromString(strDeviceId));
PageData<Rpc> rpcCalls; final DeferredResult<ResponseEntity> response = new DeferredResult<>();
if (rpcStatus != null) {
rpcCalls = rpcService.findAllByDeviceIdAndStatus(tenantId, deviceId, rpcStatus, pageLink); accessValidator.validate(getCurrentUser(), Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<>() {
} else { @Override
rpcCalls = rpcService.findAllByDeviceId(tenantId, deviceId, pageLink); public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
} PageData<Rpc> rpcCalls;
response.setResult(new ResponseEntity<>(rpcCalls, HttpStatus.OK)); if (rpcStatus != null) {
rpcCalls = rpcService.findAllByDeviceIdAndStatus(tenantId, deviceId, rpcStatus, pageLink);
} else {
rpcCalls = rpcService.findAllByDeviceId(tenantId, deviceId, pageLink);
} }
response.setResult(new ResponseEntity<>(rpcCalls, HttpStatus.OK));
}
@Override @Override
public void onFailure(Throwable e) { public void onFailure(Throwable e) {
ResponseEntity entity; ResponseEntity entity;
if (e instanceof ToErrorResponseEntity) { if (e instanceof ToErrorResponseEntity) {
entity = ((ToErrorResponseEntity) e).toErrorResponseEntity(); entity = ((ToErrorResponseEntity) e).toErrorResponseEntity();
} else { } else {
entity = new ResponseEntity(HttpStatus.UNAUTHORIZED); entity = new ResponseEntity(HttpStatus.UNAUTHORIZED);
}
response.setResult(entity);
} }
})); response.setResult(entity);
return response; }
} catch (Exception e) { }));
throw handleException(e); return response;
}
} }
@ApiOperation(value = "Delete persistent RPC", notes = "Deletes the persistent RPC request." + TENANT_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Delete persistent RPC", notes = "Deletes the persistent RPC request." + TENANT_AUTHORITY_PARAGRAPH)
@ -234,25 +226,21 @@ public class RpcV2Controller extends AbstractRpcController {
@ApiParam(value = RPC_ID_PARAM_DESCRIPTION, required = true) @ApiParam(value = RPC_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(RPC_ID) String strRpc) throws ThingsboardException { @PathVariable(RPC_ID) String strRpc) throws ThingsboardException {
checkParameter("RpcId", strRpc); checkParameter("RpcId", strRpc);
try { RpcId rpcId = new RpcId(UUID.fromString(strRpc));
RpcId rpcId = new RpcId(UUID.fromString(strRpc)); Rpc rpc = checkRpcId(rpcId, Operation.DELETE);
Rpc rpc = checkRpcId(rpcId, Operation.DELETE);
if (rpc != null) {
if (rpc != null) { if (rpc.getStatus().equals(RpcStatus.QUEUED)) {
if (rpc.getStatus().equals(RpcStatus.QUEUED)) { RemoveRpcActorMsg removeMsg = new RemoveRpcActorMsg(getTenantId(), rpc.getDeviceId(), rpc.getUuidId());
RemoveRpcActorMsg removeMsg = new RemoveRpcActorMsg(getTenantId(), rpc.getDeviceId(), rpc.getUuidId()); log.trace("[{}] Forwarding msg {} to queue actor!", rpc.getDeviceId(), rpc);
log.trace("[{}] Forwarding msg {} to queue actor!", rpc.getDeviceId(), rpc); tbClusterService.pushMsgToCore(removeMsg, null);
tbClusterService.pushMsgToCore(removeMsg, null); }
}
rpcService.deleteRpc(getTenantId(), rpcId); rpcService.deleteRpc(getTenantId(), rpcId);
rpc.setStatus(RpcStatus.DELETED); rpc.setStatus(RpcStatus.DELETED);
TbMsg msg = TbMsg.newMsg(RPC_DELETED, rpc.getDeviceId(), TbMsgMetaData.EMPTY, JacksonUtil.toString(rpc)); TbMsg msg = TbMsg.newMsg(RPC_DELETED, rpc.getDeviceId(), TbMsgMetaData.EMPTY, JacksonUtil.toString(rpc));
tbClusterService.pushMsgToRuleEngine(getTenantId(), rpc.getDeviceId(), msg, null); tbClusterService.pushMsgToRuleEngine(getTenantId(), rpc.getDeviceId(), msg, null);
}
} catch (Exception e) {
throw handleException(e);
} }
} }
} }

265
application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -166,12 +167,8 @@ public class RuleChainController extends BaseController {
@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION)
@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
checkParameter(RULE_CHAIN_ID, strRuleChainId); checkParameter(RULE_CHAIN_ID, strRuleChainId);
try { RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); return checkRuleChain(ruleChainId, Operation.READ);
return checkRuleChain(ruleChainId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Rule Chain output labels (getRuleChainOutputLabels)", @ApiOperation(value = "Get Rule Chain output labels (getRuleChainOutputLabels)",
@ -184,13 +181,9 @@ public class RuleChainController extends BaseController {
@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION)
@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
checkParameter(RULE_CHAIN_ID, strRuleChainId); checkParameter(RULE_CHAIN_ID, strRuleChainId);
try { RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); checkRuleChain(ruleChainId, Operation.READ);
checkRuleChain(ruleChainId, Operation.READ); return tbRuleChainService.getRuleChainOutputLabels(getTenantId(), ruleChainId);
return tbRuleChainService.getRuleChainOutputLabels(getTenantId(), ruleChainId);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get output labels usage (getRuleChainOutputLabelsUsage)", @ApiOperation(value = "Get output labels usage (getRuleChainOutputLabelsUsage)",
@ -203,13 +196,9 @@ public class RuleChainController extends BaseController {
@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION)
@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
checkParameter(RULE_CHAIN_ID, strRuleChainId); checkParameter(RULE_CHAIN_ID, strRuleChainId);
try { RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); checkRuleChain(ruleChainId, Operation.READ);
checkRuleChain(ruleChainId, Operation.READ); return tbRuleChainService.getOutputLabelUsage(getCurrentUser().getTenantId(), ruleChainId);
return tbRuleChainService.getOutputLabelUsage(getCurrentUser().getTenantId(), ruleChainId);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Rule Chain (getRuleChainById)", @ApiOperation(value = "Get Rule Chain (getRuleChainById)",
@ -221,13 +210,9 @@ public class RuleChainController extends BaseController {
@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION)
@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
checkParameter(RULE_CHAIN_ID, strRuleChainId); checkParameter(RULE_CHAIN_ID, strRuleChainId);
try { RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); checkRuleChain(ruleChainId, Operation.READ);
checkRuleChain(ruleChainId, Operation.READ); return ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChainId);
return ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChainId);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Rule Chain (saveRuleChain)", @ApiOperation(value = "Create Or Update Rule Chain (saveRuleChain)",
@ -319,17 +304,13 @@ public class RuleChainController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); RuleChainType type = RuleChainType.CORE;
RuleChainType type = RuleChainType.CORE; if (typeStr != null && typeStr.trim().length() > 0) {
if (typeStr != null && typeStr.trim().length() > 0) { type = RuleChainType.valueOf(typeStr);
type = RuleChainType.valueOf(typeStr);
}
return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink));
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink));
} }
@ApiOperation(value = "Delete rule chain (deleteRuleChain)", @ApiOperation(value = "Delete rule chain (deleteRuleChain)",
@ -357,25 +338,21 @@ public class RuleChainController extends BaseController {
@ApiParam(value = RULE_NODE_ID_PARAM_DESCRIPTION) @ApiParam(value = RULE_NODE_ID_PARAM_DESCRIPTION)
@PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException { @PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException {
checkParameter(RULE_NODE_ID, strRuleNodeId); checkParameter(RULE_NODE_ID, strRuleNodeId);
try { RuleNodeId ruleNodeId = new RuleNodeId(toUUID(strRuleNodeId));
RuleNodeId ruleNodeId = new RuleNodeId(toUUID(strRuleNodeId)); checkRuleNode(ruleNodeId, Operation.READ);
checkRuleNode(ruleNodeId, Operation.READ); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); List<EventInfo> events = eventService.findLatestEvents(tenantId, ruleNodeId, EventType.DEBUG_RULE_NODE, 2);
List<EventInfo> events = eventService.findLatestEvents(tenantId, ruleNodeId, EventType.DEBUG_RULE_NODE, 2); JsonNode result = null;
JsonNode result = null; if (events != null) {
if (events != null) { for (EventInfo event : events) {
for (EventInfo event : events) { JsonNode body = event.getBody();
JsonNode body = event.getBody(); if (body.has("type") && body.get("type").asText().equals("IN")) {
if (body.has("type") && body.get("type").asText().equals("IN")) { result = body;
result = body; break;
break;
}
} }
} }
return result;
} catch (Exception e) {
throw handleException(e);
} }
return result;
} }
@ApiOperation(value = "Is TBEL script executor enabled", @ApiOperation(value = "Is TBEL script executor enabled",
@ -396,74 +373,70 @@ public class RuleChainController extends BaseController {
@ApiParam(value = "Script language: JS or TBEL") @ApiParam(value = "Script language: JS or TBEL")
@RequestParam(required = false) ScriptLanguage scriptLang, @RequestParam(required = false) ScriptLanguage scriptLang,
@ApiParam(value = "Test JS request. See API call description above.") @ApiParam(value = "Test JS request. See API call description above.")
@RequestBody JsonNode inputParams) throws ThingsboardException { @RequestBody JsonNode inputParams) throws ThingsboardException, JsonProcessingException {
String script = inputParams.get("script").asText();
String scriptType = inputParams.get("scriptType").asText();
JsonNode argNamesJson = inputParams.get("argNames");
String[] argNames = objectMapper.treeToValue(argNamesJson, String[].class);
String data = inputParams.get("msg").asText();
JsonNode metadataJson = inputParams.get("metadata");
Map<String, String> metadata = objectMapper.convertValue(metadataJson, new TypeReference<Map<String, String>>() {
});
String msgType = inputParams.get("msgType").asText();
String output = "";
String errorText = "";
ScriptEngine engine = null;
try { try {
String script = inputParams.get("script").asText(); if (scriptLang == null) {
String scriptType = inputParams.get("scriptType").asText(); scriptLang = ScriptLanguage.JS;
JsonNode argNamesJson = inputParams.get("argNames"); }
String[] argNames = objectMapper.treeToValue(argNamesJson, String[].class); if (ScriptLanguage.JS.equals(scriptLang)) {
engine = new RuleNodeJsScriptEngine(getTenantId(), jsInvokeService, script, argNames);
String data = inputParams.get("msg").asText(); } else {
JsonNode metadataJson = inputParams.get("metadata"); if (tbelInvokeService == null) {
Map<String, String> metadata = objectMapper.convertValue(metadataJson, new TypeReference<Map<String, String>>() { throw new IllegalArgumentException("TBEL script engine is disabled!");
});
String msgType = inputParams.get("msgType").asText();
String output = "";
String errorText = "";
ScriptEngine engine = null;
try {
if (scriptLang == null) {
scriptLang = ScriptLanguage.JS;
}
if (ScriptLanguage.JS.equals(scriptLang)) {
engine = new RuleNodeJsScriptEngine(getTenantId(), jsInvokeService, script, argNames);
} else {
if (tbelInvokeService == null) {
throw new IllegalArgumentException("TBEL script engine is disabled!");
}
engine = new RuleNodeTbelScriptEngine(getTenantId(), tbelInvokeService, script, argNames);
}
TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data);
switch (scriptType) {
case "update":
output = msgToOutput(engine.executeUpdateAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS));
break;
case "generate":
output = msgToOutput(engine.executeGenerateAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS));
break;
case "filter":
boolean result = engine.executeFilterAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = Boolean.toString(result);
break;
case "switch":
Set<String> states = engine.executeSwitchAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = objectMapper.writeValueAsString(states);
break;
case "json":
JsonNode json = engine.executeJsonAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = objectMapper.writeValueAsString(json);
break;
case "string":
output = engine.executeToStringAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
break;
default:
throw new IllegalArgumentException("Unsupported script type: " + scriptType);
}
} catch (Exception e) {
log.error("Error evaluating JS function", e);
errorText = e.getMessage();
} finally {
if (engine != null) {
engine.destroy();
} }
engine = new RuleNodeTbelScriptEngine(getTenantId(), tbelInvokeService, script, argNames);
}
TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data);
switch (scriptType) {
case "update":
output = msgToOutput(engine.executeUpdateAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS));
break;
case "generate":
output = msgToOutput(engine.executeGenerateAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS));
break;
case "filter":
boolean result = engine.executeFilterAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = Boolean.toString(result);
break;
case "switch":
Set<String> states = engine.executeSwitchAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = objectMapper.writeValueAsString(states);
break;
case "json":
JsonNode json = engine.executeJsonAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = objectMapper.writeValueAsString(json);
break;
case "string":
output = engine.executeToStringAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
break;
default:
throw new IllegalArgumentException("Unsupported script type: " + scriptType);
} }
ObjectNode result = objectMapper.createObjectNode();
result.put("output", output);
result.put("error", errorText);
return result;
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); log.error("Error evaluating JS function", e);
errorText = e.getMessage();
} finally {
if (engine != null) {
engine.destroy();
}
} }
ObjectNode result = objectMapper.createObjectNode();
result.put("output", output);
result.put("error", errorText);
return result;
} }
@ApiOperation(value = "Export Rule Chains", notes = "Exports all tenant rule chains as one JSON." + TENANT_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Export Rule Chains", notes = "Exports all tenant rule chains as one JSON." + TENANT_AUTHORITY_PARAGRAPH)
@ -473,13 +446,9 @@ public class RuleChainController extends BaseController {
public RuleChainData exportRuleChains( public RuleChainData exportRuleChains(
@ApiParam(value = "A limit of rule chains to export.", required = true) @ApiParam(value = "A limit of rule chains to export.", required = true)
@RequestParam("limit") int limit) throws ThingsboardException { @RequestParam("limit") int limit) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = new PageLink(limit);
PageLink pageLink = new PageLink(limit); return checkNotNull(ruleChainService.exportTenantRuleChains(tenantId, pageLink));
return checkNotNull(ruleChainService.exportTenantRuleChains(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Import Rule Chains", notes = "Imports all tenant rule chains as one JSON." + TENANT_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Import Rule Chains", notes = "Imports all tenant rule chains as one JSON." + TENANT_AUTHORITY_PARAGRAPH)
@ -491,19 +460,15 @@ public class RuleChainController extends BaseController {
@RequestBody RuleChainData ruleChainData, @RequestBody RuleChainData ruleChainData,
@ApiParam(value = "Enables overwrite for existing rule chains with the same name.") @ApiParam(value = "Enables overwrite for existing rule chains with the same name.")
@RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException { @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, overwrite);
List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, overwrite); for (RuleChainImportResult importResult : importResults) {
for (RuleChainImportResult importResult : importResults) { if (importResult.getError() == null) {
if (importResult.getError() == null) { tbClusterService.broadcastEntityStateChangeEvent(importResult.getTenantId(), importResult.getRuleChainId(),
tbClusterService.broadcastEntityStateChangeEvent(importResult.getTenantId(), importResult.getRuleChainId(), importResult.isUpdated() ? ComponentLifecycleEvent.UPDATED : ComponentLifecycleEvent.CREATED);
importResult.isUpdated() ? ComponentLifecycleEvent.UPDATED : ComponentLifecycleEvent.CREATED);
}
} }
return importResults;
} catch (Exception e) {
throw handleException(e);
} }
return importResults;
} }
private String msgToOutput(TbMsg msg) throws Exception { private String msgToOutput(TbMsg msg) throws Exception {
@ -601,15 +566,11 @@ public class RuleChainController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId); checkParameter(EDGE_ID, strEdgeId);
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); checkEdgeId(edgeId, Operation.READ);
checkEdgeId(edgeId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink));
return checkNotNull(ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Set Edge Template Root Rule Chain (setEdgeTemplateRootRuleChain)", @ApiOperation(value = "Set Edge Template Root Rule Chain (setEdgeTemplateRootRuleChain)",
@ -661,17 +622,13 @@ public class RuleChainController extends BaseController {
@RequestMapping(value = "/ruleChain/autoAssignToEdgeRuleChains", method = RequestMethod.GET) @RequestMapping(value = "/ruleChain/autoAssignToEdgeRuleChains", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<RuleChain> getAutoAssignToEdgeRuleChains() throws ThingsboardException { public List<RuleChain> getAutoAssignToEdgeRuleChains() throws ThingsboardException {
try { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); List<RuleChain> result = new ArrayList<>();
List<RuleChain> result = new ArrayList<>(); PageDataIterableByTenant<RuleChain> autoAssignRuleChainsIterator =
PageDataIterableByTenant<RuleChain> autoAssignRuleChainsIterator = new PageDataIterableByTenant<>(ruleChainService::findAutoAssignToEdgeRuleChainsByTenantId, tenantId, DEFAULT_PAGE_SIZE);
new PageDataIterableByTenant<>(ruleChainService::findAutoAssignToEdgeRuleChainsByTenantId, tenantId, DEFAULT_PAGE_SIZE); for (RuleChain ruleChain : autoAssignRuleChainsIterator) {
for (RuleChain ruleChain : autoAssignRuleChainsIterator) { result.add(ruleChain);
result.add(ruleChain);
}
return checkNotNull(result);
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(result);
} }
} }

66
application/src/main/java/org/thingsboard/server/controller/TbResourceController.java

@ -82,20 +82,16 @@ public class TbResourceController extends BaseController {
public ResponseEntity<org.springframework.core.io.Resource> downloadResource(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) public ResponseEntity<org.springframework.core.io.Resource> downloadResource(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
@PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException {
checkParameter(RESOURCE_ID, strResourceId); checkParameter(RESOURCE_ID, strResourceId);
try { TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); TbResource tbResource = checkResourceId(resourceId, Operation.READ);
TbResource tbResource = checkResourceId(resourceId, Operation.READ);
ByteArrayResource resource = new ByteArrayResource(Base64.getDecoder().decode(tbResource.getData().getBytes())); ByteArrayResource resource = new ByteArrayResource(Base64.getDecoder().decode(tbResource.getData().getBytes()));
return ResponseEntity.ok() return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + tbResource.getFileName()) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + tbResource.getFileName())
.header("x-filename", tbResource.getFileName()) .header("x-filename", tbResource.getFileName())
.contentLength(resource.contentLength()) .contentLength(resource.contentLength())
.contentType(MediaType.APPLICATION_OCTET_STREAM) .contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource); .body(resource);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Resource Info (getResourceInfoById)", @ApiOperation(value = "Get Resource Info (getResourceInfoById)",
@ -108,12 +104,8 @@ public class TbResourceController extends BaseController {
public TbResourceInfo getResourceInfoById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) public TbResourceInfo getResourceInfoById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
@PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException {
checkParameter(RESOURCE_ID, strResourceId); checkParameter(RESOURCE_ID, strResourceId);
try { TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); return checkResourceInfoId(resourceId, Operation.READ);
return checkResourceInfoId(resourceId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Resource (getResourceById)", @ApiOperation(value = "Get Resource (getResourceById)",
@ -126,12 +118,8 @@ public class TbResourceController extends BaseController {
public TbResource getResourceById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) public TbResource getResourceById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION)
@PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException {
checkParameter(RESOURCE_ID, strResourceId); checkParameter(RESOURCE_ID, strResourceId);
try { TbResourceId resourceId = new TbResourceId(toUUID(strResourceId));
TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); return checkResourceId(resourceId, Operation.READ);
return checkResourceId(resourceId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Resource (saveResource)", @ApiOperation(value = "Create Or Update Resource (saveResource)",
@ -171,15 +159,11 @@ public class TbResourceController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { return checkNotNull(resourceService.findTenantResourcesByTenantId(getTenantId(), pageLink));
return checkNotNull(resourceService.findTenantResourcesByTenantId(getTenantId(), pageLink)); } else {
} else { return checkNotNull(resourceService.findAllTenantResourcesByTenantId(getTenantId(), pageLink));
return checkNotNull(resourceService.findAllTenantResourcesByTenantId(getTenantId(), pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -200,12 +184,8 @@ public class TbResourceController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = new PageLink(pageSize, page, textSearch);
PageLink pageLink = new PageLink(pageSize, page, textSearch); return checkNotNull(resourceService.findLwM2mObjectPage(getTenantId(), sortProperty, sortOrder, pageLink));
return checkNotNull(resourceService.findLwM2mObjectPage(getTenantId(), sortProperty, sortOrder, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)", @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)",
@ -221,11 +201,7 @@ public class TbResourceController extends BaseController {
@RequestParam String sortProperty, @RequestParam String sortProperty,
@ApiParam(value = "LwM2M Object ids.", required = true) @ApiParam(value = "LwM2M Object ids.", required = true)
@RequestParam(required = false) String[] objectIds) throws ThingsboardException { @RequestParam(required = false) String[] objectIds) throws ThingsboardException {
try { return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds));
return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Delete Resource (deleteResource)", @ApiOperation(value = "Delete Resource (deleteResource)",

128
application/src/main/java/org/thingsboard/server/controller/TelemetryController.java

@ -184,11 +184,7 @@ public class TelemetryController extends BaseController {
public DeferredResult<ResponseEntity> getAttributeKeys( public DeferredResult<ResponseEntity> getAttributeKeys(
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType,
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException { @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException {
try { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, this::getAttributeKeysCallback);
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, this::getAttributeKeysCallback);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get all attribute keys by scope (getAttributeKeysByScope)", @ApiOperation(value = "Get all attribute keys by scope (getAttributeKeysByScope)",
@ -205,12 +201,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType,
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope) throws ThingsboardException {
try { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr,
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr,
(result, tenantId, entityId) -> getAttributeKeysCallback(result, tenantId, entityId, scope)); (result, tenantId, entityId) -> getAttributeKeysCallback(result, tenantId, entityId, scope));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get attributes (getAttributes)", @ApiOperation(value = "Get attributes (getAttributes)",
@ -228,13 +220,9 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType,
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException {
try {
SecurityUser user = getCurrentUser(); SecurityUser user = getCurrentUser();
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr,
(result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, null, keysStr)); (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, null, keysStr));
} catch (Exception e) {
throw handleException(e);
}
} }
@ -256,13 +244,9 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope,
@ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException {
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr,
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr,
(result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, scope, keysStr)); (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, scope, keysStr));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get time-series keys (getTimeseriesKeys)", @ApiOperation(value = "Get time-series keys (getTimeseriesKeys)",
@ -275,12 +259,8 @@ public class TelemetryController extends BaseController {
public DeferredResult<ResponseEntity> getTimeseriesKeys( public DeferredResult<ResponseEntity> getTimeseriesKeys(
@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType,
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException { @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException {
try { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
(result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor())); (result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get latest time-series value (getLatestTimeseries)", @ApiOperation(value = "Get latest time-series value (getLatestTimeseries)",
@ -305,13 +285,9 @@ public class TelemetryController extends BaseController {
@ApiParam(value = TELEMETRY_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr, @ApiParam(value = TELEMETRY_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr,
@ApiParam(value = STRICT_DATA_TYPES_DESCRIPTION) @ApiParam(value = STRICT_DATA_TYPES_DESCRIPTION)
@RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
try { SecurityUser user = getCurrentUser();
SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes));
(result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get time-series data (getTimeseries)", @ApiOperation(value = "Get time-series data (getTimeseries)",
@ -348,19 +324,15 @@ public class TelemetryController extends BaseController {
@RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy, @RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy,
@ApiParam(value = STRICT_DATA_TYPES_DESCRIPTION) @ApiParam(value = STRICT_DATA_TYPES_DESCRIPTION)
@RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException {
try { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr,
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, (result, tenantId, entityId) -> {
(result, tenantId, entityId) -> { // If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted
// If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted Aggregation agg = interval == 0L ? Aggregation.valueOf(Aggregation.NONE.name()) : Aggregation.valueOf(aggStr);
Aggregation agg = interval == 0L ? Aggregation.valueOf(Aggregation.NONE.name()) : Aggregation.valueOf(aggStr); List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg, orderBy))
List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg, orderBy)) .collect(Collectors.toList());
.collect(Collectors.toList());
Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes), MoreExecutors.directExecutor());
Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes), MoreExecutors.directExecutor()); });
});
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Save device attributes (saveDeviceAttributes)", @ApiOperation(value = "Save device attributes (saveDeviceAttributes)",
@ -384,12 +356,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr, @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope,
@ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); return saveAttributes(getTenantId(), entityId, scope, request);
return saveAttributes(getTenantId(), entityId, scope, request);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Save entity attributes (saveEntityAttributesV1)", @ApiOperation(value = "Save entity attributes (saveEntityAttributesV1)",
@ -412,12 +380,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope, @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope,
@ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveAttributes(getTenantId(), entityId, scope, request);
return saveAttributes(getTenantId(), entityId, scope, request);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Save entity attributes (saveEntityAttributesV2)", @ApiOperation(value = "Save entity attributes (saveEntityAttributesV2)",
@ -440,12 +404,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope,
@ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveAttributes(getTenantId(), entityId, scope, request);
return saveAttributes(getTenantId(), entityId, scope, request);
} catch (Exception e) {
throw handleException(e);
}
} }
@ -469,12 +429,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = TELEMETRY_SCOPE_DESCRIPTION, required = true, allowableValues = "ANY") @PathVariable("scope") String scope, @ApiParam(value = TELEMETRY_SCOPE_DESCRIPTION, required = true, allowableValues = "ANY") @PathVariable("scope") String scope,
@ApiParam(value = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody String requestBody) throws ThingsboardException { @ApiParam(value = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody String requestBody) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveTelemetry(getTenantId(), entityId, requestBody, 0L);
return saveTelemetry(getTenantId(), entityId, requestBody, 0L);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Save or update time-series data with TTL (saveEntityTelemetryWithTTL)", @ApiOperation(value = "Save or update time-series data with TTL (saveEntityTelemetryWithTTL)",
@ -499,12 +455,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = TELEMETRY_SCOPE_DESCRIPTION, required = true, allowableValues = "ANY") @PathVariable("scope") String scope, @ApiParam(value = TELEMETRY_SCOPE_DESCRIPTION, required = true, allowableValues = "ANY") @PathVariable("scope") String scope,
@ApiParam(value = "A long value representing TTL (Time to Live) parameter.", required = true) @PathVariable("ttl") Long ttl, @ApiParam(value = "A long value representing TTL (Time to Live) parameter.", required = true) @PathVariable("ttl") Long ttl,
@ApiParam(value = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody String requestBody) throws ThingsboardException { @ApiParam(value = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody String requestBody) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveTelemetry(getTenantId(), entityId, requestBody, ttl);
return saveTelemetry(getTenantId(), entityId, requestBody, ttl);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Delete entity time-series data (deleteEntityTimeseries)", @ApiOperation(value = "Delete entity time-series data (deleteEntityTimeseries)",
@ -537,12 +489,8 @@ public class TelemetryController extends BaseController {
@RequestParam(name = "endTs", required = false) Long endTs, @RequestParam(name = "endTs", required = false) Long endTs,
@ApiParam(value = "If the parameter is set to true, the latest telemetry will be rewritten in case that current latest value was removed, otherwise, in case that parameter is set to false the new latest value will not set.") @ApiParam(value = "If the parameter is set to true, the latest telemetry will be rewritten in case that current latest value was removed, otherwise, in case that parameter is set to false the new latest value will not set.")
@RequestParam(name = "rewriteLatestIfDeleted", defaultValue = "false") boolean rewriteLatestIfDeleted) throws ThingsboardException { @RequestParam(name = "rewriteLatestIfDeleted", defaultValue = "false") boolean rewriteLatestIfDeleted) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return deleteTimeseries(entityId, keysStr, deleteAllDataForKeys, startTs, endTs, rewriteLatestIfDeleted);
return deleteTimeseries(entityId, keysStr, deleteAllDataForKeys, startTs, endTs, rewriteLatestIfDeleted);
} catch (Exception e) {
throw handleException(e);
}
} }
private DeferredResult<ResponseEntity> deleteTimeseries(EntityId entityIdStr, String keysStr, boolean deleteAllDataForKeys, private DeferredResult<ResponseEntity> deleteTimeseries(EntityId entityIdStr, String keysStr, boolean deleteAllDataForKeys,
@ -607,12 +555,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(DEVICE_ID) String deviceIdStr, @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(DEVICE_ID) String deviceIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope,
@ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); return deleteAttributes(entityId, scope, keysStr);
return deleteAttributes(entityId, scope, keysStr);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)", @ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)",
@ -635,12 +579,8 @@ public class TelemetryController extends BaseController {
@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope, @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope,
@ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr) throws ThingsboardException { @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr) throws ThingsboardException {
try { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return deleteAttributes(entityId, scope, keysStr);
return deleteAttributes(entityId, scope, keysStr);
} catch (Exception e) {
throw handleException(e);
}
} }
private DeferredResult<ResponseEntity> deleteAttributes(EntityId entityIdSrc, String scope, String keysStr) throws ThingsboardException { private DeferredResult<ResponseEntity> deleteAttributes(EntityId entityIdSrc, String scope, String keysStr) throws ThingsboardException {

38
application/src/main/java/org/thingsboard/server/controller/TenantController.java

@ -79,16 +79,12 @@ public class TenantController extends BaseController {
@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION)
@PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException { @PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException {
checkParameter(TENANT_ID, strTenantId); checkParameter(TENANT_ID, strTenantId);
try { TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId));
TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); Tenant tenant = checkTenantId(tenantId, Operation.READ);
Tenant tenant = checkTenantId(tenantId, Operation.READ); if (!tenant.getAdditionalInfo().isNull()) {
if (!tenant.getAdditionalInfo().isNull()) { processDashboardIdFromAdditionalInfo((ObjectNode) tenant.getAdditionalInfo(), HOME_DASHBOARD);
processDashboardIdFromAdditionalInfo((ObjectNode) tenant.getAdditionalInfo(), HOME_DASHBOARD);
}
return tenant;
} catch (Exception e) {
throw handleException(e);
} }
return tenant;
} }
@ApiOperation(value = "Get Tenant Info (getTenantInfoById)", @ApiOperation(value = "Get Tenant Info (getTenantInfoById)",
@ -101,12 +97,8 @@ public class TenantController extends BaseController {
@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION)
@PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException { @PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException {
checkParameter(TENANT_ID, strTenantId); checkParameter(TENANT_ID, strTenantId);
try { TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId));
TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); return checkTenantInfoId(tenantId, Operation.READ);
return checkTenantInfoId(tenantId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or update Tenant (saveTenant)", @ApiOperation(value = "Create Or update Tenant (saveTenant)",
@ -154,12 +146,8 @@ public class TenantController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantService.findTenants(pageLink));
return checkNotNull(tenantService.findTenants(pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Tenants Info (getTenants)", notes = "Returns a page of tenant info objects registered in the platform. " @ApiOperation(value = "Get Tenants Info (getTenants)", notes = "Returns a page of tenant info objects registered in the platform. "
@ -179,12 +167,8 @@ public class TenantController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder @RequestParam(required = false) String sortOrder
) throws ThingsboardException { ) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantService.findTenantInfos(pageLink));
return checkNotNull(tenantService.findTenantInfos(pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
} }

82
application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java

@ -82,12 +82,8 @@ public class TenantProfileController extends BaseController {
@ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException {
checkParameter("tenantProfileId", strTenantProfileId); checkParameter("tenantProfileId", strTenantProfileId);
try { TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId));
TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); return checkTenantProfileId(tenantProfileId, Operation.READ);
return checkTenantProfileId(tenantProfileId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Tenant Profile Info (getTenantProfileInfoById)", @ApiOperation(value = "Get Tenant Profile Info (getTenantProfileInfoById)",
@ -99,12 +95,8 @@ public class TenantProfileController extends BaseController {
@ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException {
checkParameter("tenantProfileId", strTenantProfileId); checkParameter("tenantProfileId", strTenantProfileId);
try { TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId));
TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); return checkNotNull(tenantProfileService.findTenantProfileInfoById(getTenantId(), tenantProfileId));
return checkNotNull(tenantProfileService.findTenantProfileInfoById(getTenantId(), tenantProfileId));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get default Tenant Profile Info (getDefaultTenantProfileInfo)", @ApiOperation(value = "Get default Tenant Profile Info (getDefaultTenantProfileInfo)",
@ -113,11 +105,7 @@ public class TenantProfileController extends BaseController {
@RequestMapping(value = "/tenantProfileInfo/default", method = RequestMethod.GET) @RequestMapping(value = "/tenantProfileInfo/default", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public EntityInfo getDefaultTenantProfileInfo() throws ThingsboardException { public EntityInfo getDefaultTenantProfileInfo() throws ThingsboardException {
try { return checkNotNull(tenantProfileService.findDefaultTenantProfileInfo(getTenantId()));
return checkNotNull(tenantProfileService.findDefaultTenantProfileInfo(getTenantId()));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or update Tenant Profile (saveTenantProfile)", @ApiOperation(value = "Create Or update Tenant Profile (saveTenantProfile)",
@ -178,19 +166,15 @@ public class TenantProfileController extends BaseController {
@ResponseBody @ResponseBody
public TenantProfile saveTenantProfile(@ApiParam(value = "A JSON value representing the tenant profile.") public TenantProfile saveTenantProfile(@ApiParam(value = "A JSON value representing the tenant profile.")
@RequestBody TenantProfile tenantProfile) throws ThingsboardException { @RequestBody TenantProfile tenantProfile) throws ThingsboardException {
try { TenantProfile oldProfile;
TenantProfile oldProfile; if (tenantProfile.getId() == null) {
if (tenantProfile.getId() == null) { accessControlService.checkPermission(getCurrentUser(), Resource.TENANT_PROFILE, Operation.CREATE);
accessControlService.checkPermission(getCurrentUser(), Resource.TENANT_PROFILE, Operation.CREATE); oldProfile = null;
oldProfile = null; } else {
} else { oldProfile = checkTenantProfileId(tenantProfile.getId(), Operation.WRITE);
oldProfile = checkTenantProfileId(tenantProfile.getId(), Operation.WRITE);
}
return tbTenantProfileService.save(getTenantId(), tenantProfile, oldProfile);
} catch (Exception e) {
throw handleException(e);
} }
return tbTenantProfileService.save(getTenantId(), tenantProfile, oldProfile);
} }
@ApiOperation(value = "Delete Tenant Profile (deleteTenantProfile)", @ApiOperation(value = "Delete Tenant Profile (deleteTenantProfile)",
@ -200,14 +184,10 @@ public class TenantProfileController extends BaseController {
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public void deleteTenantProfile(@ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) public void deleteTenantProfile(@ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException {
try { checkParameter("tenantProfileId", strTenantProfileId);
checkParameter("tenantProfileId", strTenantProfileId); TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId));
TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); TenantProfile profile = checkTenantProfileId(tenantProfileId, Operation.DELETE);
TenantProfile profile = checkTenantProfileId(tenantProfileId, Operation.DELETE); tbTenantProfileService.delete(getTenantId(), profile);
tbTenantProfileService.delete(getTenantId(), profile);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Make tenant profile default (setDefaultTenantProfile)", @ApiOperation(value = "Make tenant profile default (setDefaultTenantProfile)",
@ -219,14 +199,10 @@ public class TenantProfileController extends BaseController {
@ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION)
@PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException {
checkParameter("tenantProfileId", strTenantProfileId); checkParameter("tenantProfileId", strTenantProfileId);
try { TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId));
TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); TenantProfile tenantProfile = checkTenantProfileId(tenantProfileId, Operation.WRITE);
TenantProfile tenantProfile = checkTenantProfileId(tenantProfileId, Operation.WRITE); tenantProfileService.setDefaultTenantProfile(getTenantId(), tenantProfileId);
tenantProfileService.setDefaultTenantProfile(getTenantId(), tenantProfileId); return tenantProfile;
return tenantProfile;
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Tenant Profiles (getTenantProfiles)", notes = "Returns a page of tenant profiles registered in the platform. " + PAGE_DATA_PARAMETERS + SYSTEM_AUTHORITY_PARAGRAPH) @ApiOperation(value = "Get Tenant Profiles (getTenantProfiles)", notes = "Returns a page of tenant profiles registered in the platform. " + PAGE_DATA_PARAMETERS + SYSTEM_AUTHORITY_PARAGRAPH)
@ -244,12 +220,8 @@ public class TenantProfileController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantProfileService.findTenantProfiles(getTenantId(), pageLink));
return checkNotNull(tenantProfileService.findTenantProfiles(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Tenant Profiles Info (getTenantProfileInfos)", notes = "Returns a page of tenant profile info objects registered in the platform. " @ApiOperation(value = "Get Tenant Profiles Info (getTenantProfileInfos)", notes = "Returns a page of tenant profile info objects registered in the platform. "
@ -268,12 +240,8 @@ public class TenantProfileController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantProfileService.findTenantProfileInfos(getTenantId(), pageLink));
return checkNotNull(tenantProfileService.findTenantProfileInfos(getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@GetMapping(value = "/tenantProfiles", params = {"ids"}) @GetMapping(value = "/tenantProfiles", params = {"ids"})

211
application/src/main/java/org/thingsboard/server/controller/UserController.java

@ -42,8 +42,10 @@ import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.UserEmailInfo; import org.thingsboard.server.common.data.UserEmailInfo;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -63,6 +65,7 @@ import org.thingsboard.server.common.data.settings.UserDashboardsInfo;
import org.thingsboard.server.common.data.settings.UserSettings; import org.thingsboard.server.common.data.settings.UserSettings;
import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent; import org.thingsboard.server.common.data.security.event.UserCredentialsInvalidationEvent;
import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.common.data.security.model.JwtPair;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.common.data.settings.UserSettingsType; import org.thingsboard.server.common.data.settings.UserSettingsType;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.user.TbUserService; import org.thingsboard.server.service.entitiy.user.TbUserService;
@ -75,11 +78,14 @@ import org.thingsboard.server.service.security.permission.Resource;
import org.thingsboard.server.service.security.system.SystemSecurityService; import org.thingsboard.server.service.security.system.SystemSecurityService;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD;
import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION;
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID;
import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_ID_PARAM_DESCRIPTION;
@ -125,6 +131,9 @@ public class UserController extends BaseController {
@Autowired @Autowired
private EntityQueryService entityQueryService; private EntityQueryService entityQueryService;
@Autowired
private EntityService entityService;
@ApiOperation(value = "Get User (getUserById)", @ApiOperation(value = "Get User (getUserById)",
notes = "Fetch the User object based on the provided User Id. " + notes = "Fetch the User object based on the provided User Id. " +
"If the user has the authority of 'SYS_ADMIN', the server does not perform additional checks. " + "If the user has the authority of 'SYS_ADMIN', the server does not perform additional checks. " +
@ -137,22 +146,18 @@ public class UserController extends BaseController {
@ApiParam(value = USER_ID_PARAM_DESCRIPTION) @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
@PathVariable(USER_ID) String strUserId) throws ThingsboardException { @PathVariable(USER_ID) String strUserId) throws ThingsboardException {
checkParameter(USER_ID, strUserId); checkParameter(USER_ID, strUserId);
try { UserId userId = new UserId(toUUID(strUserId));
UserId userId = new UserId(toUUID(strUserId)); User user = checkUserId(userId, Operation.READ);
User user = checkUserId(userId, Operation.READ); if (user.getAdditionalInfo().isObject()) {
if (user.getAdditionalInfo().isObject()) { ObjectNode additionalInfo = (ObjectNode) user.getAdditionalInfo();
ObjectNode additionalInfo = (ObjectNode) user.getAdditionalInfo(); processDashboardIdFromAdditionalInfo(additionalInfo, DEFAULT_DASHBOARD);
processDashboardIdFromAdditionalInfo(additionalInfo, DEFAULT_DASHBOARD); processDashboardIdFromAdditionalInfo(additionalInfo, HOME_DASHBOARD);
processDashboardIdFromAdditionalInfo(additionalInfo, HOME_DASHBOARD); UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());
UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); if (userCredentials.isEnabled() && !additionalInfo.has("userCredentialsEnabled")) {
if (userCredentials.isEnabled() && !additionalInfo.has("userCredentialsEnabled")) { additionalInfo.put("userCredentialsEnabled", true);
additionalInfo.put("userCredentialsEnabled", true);
}
} }
return user;
} catch (Exception e) {
throw handleException(e);
} }
return user;
} }
@ApiOperation(value = "Check Token Access Enabled (isUserTokenAccessEnabled)", @ApiOperation(value = "Check Token Access Enabled (isUserTokenAccessEnabled)",
@ -177,21 +182,17 @@ public class UserController extends BaseController {
@ApiParam(value = USER_ID_PARAM_DESCRIPTION) @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
@PathVariable(USER_ID) String strUserId) throws ThingsboardException { @PathVariable(USER_ID) String strUserId) throws ThingsboardException {
checkParameter(USER_ID, strUserId); checkParameter(USER_ID, strUserId);
try { if (!userTokenAccessEnabled) {
if (!userTokenAccessEnabled) { throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION, ThingsboardErrorCode.PERMISSION_DENIED);
ThingsboardErrorCode.PERMISSION_DENIED);
}
UserId userId = new UserId(toUUID(strUserId));
SecurityUser authUser = getCurrentUser();
User user = checkUserId(userId, Operation.READ);
UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
UserCredentials credentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), userId);
SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal);
return tokenFactory.createTokenPair(securityUser);
} catch (Exception e) {
throw handleException(e);
} }
UserId userId = new UserId(toUUID(strUserId));
SecurityUser authUser = getCurrentUser();
User user = checkUserId(userId, Operation.READ);
UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
UserCredentials credentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), userId);
SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal);
return tokenFactory.createTokenPair(securityUser);
} }
@ApiOperation(value = "Save Or update User (saveUser)", @ApiOperation(value = "Save Or update User (saveUser)",
@ -226,23 +227,19 @@ public class UserController extends BaseController {
@ApiParam(value = "Email of the user", required = true) @ApiParam(value = "Email of the user", required = true)
@RequestParam(value = "email") String email, @RequestParam(value = "email") String email,
HttpServletRequest request) throws ThingsboardException { HttpServletRequest request) throws ThingsboardException {
try { User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email));
User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email));
accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ,
accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ, user.getId(), user);
user.getId(), user);
UserCredentials userCredentials = userService.findUserCredentialsByUserId(getCurrentUser().getTenantId(), user.getId());
UserCredentials userCredentials = userService.findUserCredentialsByUserId(getCurrentUser().getTenantId(), user.getId()); if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) {
if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request);
String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl,
String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken());
userCredentials.getActivateToken()); mailService.sendActivationEmail(activateUrl, email);
mailService.sendActivationEmail(activateUrl, email); } else {
} else { throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -257,21 +254,17 @@ public class UserController extends BaseController {
@PathVariable(USER_ID) String strUserId, @PathVariable(USER_ID) String strUserId,
HttpServletRequest request) throws ThingsboardException { HttpServletRequest request) throws ThingsboardException {
checkParameter(USER_ID, strUserId); checkParameter(USER_ID, strUserId);
try { UserId userId = new UserId(toUUID(strUserId));
UserId userId = new UserId(toUUID(strUserId)); User user = checkUserId(userId, Operation.READ);
User user = checkUserId(userId, Operation.READ); SecurityUser authUser = getCurrentUser();
SecurityUser authUser = getCurrentUser(); UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), user.getId());
UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), user.getId()); if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) {
if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request);
String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl,
String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken());
userCredentials.getActivateToken()); return activateUrl;
return activateUrl; } else {
} else { throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -310,16 +303,12 @@ public class UserController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); SecurityUser currentUser = getCurrentUser();
SecurityUser currentUser = getCurrentUser(); if (Authority.TENANT_ADMIN.equals(currentUser.getAuthority())) {
if (Authority.TENANT_ADMIN.equals(currentUser.getAuthority())) { return checkNotNull(userService.findUsersByTenantId(currentUser.getTenantId(), pageLink));
return checkNotNull(userService.findUsersByTenantId(currentUser.getTenantId(), pageLink)); } else {
} else { return checkNotNull(userService.findCustomerUsers(currentUser.getTenantId(), currentUser.getCustomerId(), pageLink));
return checkNotNull(userService.findCustomerUsers(currentUser.getTenantId(), currentUser.getCustomerId(), pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -380,13 +369,9 @@ public class UserController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("tenantId", strTenantId); checkParameter("tenantId", strTenantId);
try { TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId));
TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(userService.findTenantAdmins(tenantId, pageLink));
return checkNotNull(userService.findTenantAdmins(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Get Customer Users (getCustomerUsers)", @ApiOperation(value = "Get Customer Users (getCustomerUsers)",
@ -408,15 +393,11 @@ public class UserController extends BaseController {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId); checkParameter("customerId", strCustomerId);
try { CustomerId customerId = new CustomerId(toUUID(strCustomerId));
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ);
checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(userService.findCustomerUsers(tenantId, customerId, pageLink));
return checkNotNull(userService.findCustomerUsers(tenantId, customerId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Enable/Disable User credentials (setUserCredentialsEnabled)", @ApiOperation(value = "Enable/Disable User credentials (setUserCredentialsEnabled)",
@ -430,15 +411,59 @@ public class UserController extends BaseController {
@ApiParam(value = "Disable (\"true\") or enable (\"false\") the credentials.", defaultValue = "true") @ApiParam(value = "Disable (\"true\") or enable (\"false\") the credentials.", defaultValue = "true")
@RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException { @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException {
checkParameter(USER_ID, strUserId); checkParameter(USER_ID, strUserId);
try { UserId userId = new UserId(toUUID(strUserId));
UserId userId = new UserId(toUUID(strUserId)); User user = checkUserId(userId, Operation.WRITE);
User user = checkUserId(userId, Operation.WRITE); TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); userService.setUserCredentialsEnabled(tenantId, userId, userCredentialsEnabled);
userService.setUserCredentialsEnabled(tenantId, userId, userCredentialsEnabled);
if (!userCredentialsEnabled) {
eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(userId));
}
}
if (!userCredentialsEnabled) { @ApiOperation(value = "Get usersForAssign (getUsersForAssign)",
eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(userId)); notes = "Returns page of user data objects that can be assigned to provided alarmId. " +
"Search is been executed by email, firstName and lastName fields. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/users/assign/{alarmId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<UserEmailInfo> getUsersForAssign(
@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("alarmId") String strAlarmId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
checkParameter("alarmId", strAlarmId);
AlarmId alarmEntityId = new AlarmId(toUUID(strAlarmId));
Alarm alarm = checkAlarmId(alarmEntityId, Operation.READ);
SecurityUser currentUser = getCurrentUser();
TenantId tenantId = currentUser.getTenantId();
CustomerId originatorCustomerId = entityService.fetchEntityCustomerId(tenantId, alarm.getOriginator()).get();
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageData<User> pageData;
if (Authority.TENANT_ADMIN.equals(currentUser.getAuthority())) {
if (alarm.getCustomerId() == null) {
pageData = userService.findTenantAdmins(tenantId, pageLink);
} else {
ArrayList<CustomerId> customerIds = new ArrayList<>(Collections.singletonList(new CustomerId(CustomerId.NULL_UUID)));
if (!CustomerId.NULL_UUID.equals(originatorCustomerId.getId())) {
customerIds.add(originatorCustomerId);
}
pageData = userService.findUsersByCustomerIds(tenantId, customerIds, pageLink);
}
} else {
pageData = userService.findCustomerUsers(tenantId, alarm.getCustomerId(), pageLink);
} }
return pageData.mapData(user -> new UserEmailInfo(user.getId(), user.getEmail(), user.getFirstName(), user.getLastName()));
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
} }

145
application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java

@ -70,12 +70,8 @@ public class WidgetTypeController extends AutoCommitController {
@ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { @PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException {
checkParameter("widgetTypeId", strWidgetTypeId); checkParameter("widgetTypeId", strWidgetTypeId);
try { WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); return checkWidgetTypeId(widgetTypeId, Operation.READ);
return checkWidgetTypeId(widgetTypeId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Widget Type (saveWidgetType)", @ApiOperation(value = "Create Or Update Widget Type (saveWidgetType)",
@ -93,32 +89,28 @@ public class WidgetTypeController extends AutoCommitController {
@ResponseBody @ResponseBody
public WidgetTypeDetails saveWidgetType( public WidgetTypeDetails saveWidgetType(
@ApiParam(value = "A JSON value representing the Widget Type Details.", required = true) @ApiParam(value = "A JSON value representing the Widget Type Details.", required = true)
@RequestBody WidgetTypeDetails widgetTypeDetails) throws ThingsboardException { @RequestBody WidgetTypeDetails widgetTypeDetails) throws Exception {
try { var currentUser = getCurrentUser();
var currentUser = getCurrentUser(); if (Authority.SYS_ADMIN.equals(currentUser.getAuthority())) {
if (Authority.SYS_ADMIN.equals(currentUser.getAuthority())) { widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID);
widgetTypeDetails.setTenantId(TenantId.SYS_TENANT_ID); } else {
} else { widgetTypeDetails.setTenantId(currentUser.getTenantId());
widgetTypeDetails.setTenantId(currentUser.getTenantId()); }
}
checkEntity(widgetTypeDetails.getId(), widgetTypeDetails, Resource.WIDGET_TYPE); checkEntity(widgetTypeDetails.getId(), widgetTypeDetails, Resource.WIDGET_TYPE);
WidgetTypeDetails savedWidgetTypeDetails = widgetTypeService.saveWidgetType(widgetTypeDetails); WidgetTypeDetails savedWidgetTypeDetails = widgetTypeService.saveWidgetType(widgetTypeDetails);
if (!Authority.SYS_ADMIN.equals(currentUser.getAuthority())) { if (!Authority.SYS_ADMIN.equals(currentUser.getAuthority())) {
WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(widgetTypeDetails.getTenantId(), widgetTypeDetails.getBundleAlias()); WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(widgetTypeDetails.getTenantId(), widgetTypeDetails.getBundleAlias());
if (widgetsBundle != null) { if (widgetsBundle != null) {
autoCommit(currentUser, widgetsBundle.getId()); autoCommit(currentUser, widgetsBundle.getId());
}
} }
}
sendEntityNotificationMsg(getTenantId(), savedWidgetTypeDetails.getId(), sendEntityNotificationMsg(getTenantId(), savedWidgetTypeDetails.getId(),
widgetTypeDetails.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED); widgetTypeDetails.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED);
return checkNotNull(savedWidgetTypeDetails); return checkNotNull(savedWidgetTypeDetails);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Delete widget type (deleteWidgetType)", @ApiOperation(value = "Delete widget type (deleteWidgetType)",
@ -128,26 +120,21 @@ public class WidgetTypeController extends AutoCommitController {
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public void deleteWidgetType( public void deleteWidgetType(
@ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { @PathVariable("widgetTypeId") String strWidgetTypeId) throws Exception {
checkParameter("widgetTypeId", strWidgetTypeId); checkParameter("widgetTypeId", strWidgetTypeId);
try { var currentUser = getCurrentUser();
var currentUser = getCurrentUser(); WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); WidgetTypeDetails wtd = checkWidgetTypeId(widgetTypeId, Operation.DELETE);
WidgetTypeDetails wtd = checkWidgetTypeId(widgetTypeId, Operation.DELETE); widgetTypeService.deleteWidgetType(currentUser.getTenantId(), widgetTypeId);
widgetTypeService.deleteWidgetType(currentUser.getTenantId(), widgetTypeId);
if (wtd != null && !Authority.SYS_ADMIN.equals(currentUser.getAuthority())) {
if (wtd != null && !Authority.SYS_ADMIN.equals(currentUser.getAuthority())) { WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(wtd.getTenantId(), wtd.getBundleAlias());
WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(wtd.getTenantId(), wtd.getBundleAlias()); if (widgetsBundle != null) {
if (widgetsBundle != null) { autoCommit(currentUser, widgetsBundle.getId());
autoCommit(currentUser, widgetsBundle.getId());
}
} }
sendEntityNotificationMsg(getTenantId(), widgetTypeId, EdgeEventActionType.DELETED);
} catch (Exception e) {
throw handleException(e);
} }
sendEntityNotificationMsg(getTenantId(), widgetTypeId, EdgeEventActionType.DELETED);
} }
@ApiOperation(value = "Get all Widget types for specified Bundle (getBundleWidgetTypes)", @ApiOperation(value = "Get all Widget types for specified Bundle (getBundleWidgetTypes)",
@ -160,17 +147,13 @@ public class WidgetTypeController extends AutoCommitController {
@RequestParam boolean isSystem, @RequestParam boolean isSystem,
@ApiParam(value = "Widget Bundle alias", required = true) @ApiParam(value = "Widget Bundle alias", required = true)
@RequestParam String bundleAlias) throws ThingsboardException { @RequestParam String bundleAlias) throws ThingsboardException {
try { TenantId tenantId;
TenantId tenantId; if (isSystem) {
if (isSystem) { tenantId = TenantId.SYS_TENANT_ID;
tenantId = TenantId.SYS_TENANT_ID; } else {
} else { tenantId = getCurrentUser().getTenantId();
tenantId = getCurrentUser().getTenantId();
}
return checkNotNull(widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(tenantId, bundleAlias));
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(tenantId, bundleAlias));
} }
@ApiOperation(value = "Get all Widget types details for specified Bundle (getBundleWidgetTypes)", @ApiOperation(value = "Get all Widget types details for specified Bundle (getBundleWidgetTypes)",
@ -183,17 +166,13 @@ public class WidgetTypeController extends AutoCommitController {
@RequestParam boolean isSystem, @RequestParam boolean isSystem,
@ApiParam(value = "Widget Bundle alias", required = true) @ApiParam(value = "Widget Bundle alias", required = true)
@RequestParam String bundleAlias) throws ThingsboardException { @RequestParam String bundleAlias) throws ThingsboardException {
try { TenantId tenantId;
TenantId tenantId; if (isSystem) {
if (isSystem) { tenantId = TenantId.SYS_TENANT_ID;
tenantId = TenantId.SYS_TENANT_ID; } else {
} else { tenantId = getCurrentUser().getTenantId();
tenantId = getCurrentUser().getTenantId();
}
return checkNotNull(widgetTypeService.findWidgetTypesDetailsByTenantIdAndBundleAlias(tenantId, bundleAlias));
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(widgetTypeService.findWidgetTypesDetailsByTenantIdAndBundleAlias(tenantId, bundleAlias));
} }
@ApiOperation(value = "Get Widget Type Info objects (getBundleWidgetTypesInfos)", @ApiOperation(value = "Get Widget Type Info objects (getBundleWidgetTypesInfos)",
@ -206,17 +185,13 @@ public class WidgetTypeController extends AutoCommitController {
@RequestParam boolean isSystem, @RequestParam boolean isSystem,
@ApiParam(value = "Widget Bundle alias", required = true) @ApiParam(value = "Widget Bundle alias", required = true)
@RequestParam String bundleAlias) throws ThingsboardException { @RequestParam String bundleAlias) throws ThingsboardException {
try { TenantId tenantId;
TenantId tenantId; if (isSystem) {
if (isSystem) { tenantId = TenantId.SYS_TENANT_ID;
tenantId = TenantId.SYS_TENANT_ID; } else {
} else { tenantId = getCurrentUser().getTenantId();
tenantId = getCurrentUser().getTenantId();
}
return checkNotNull(widgetTypeService.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, bundleAlias));
} catch (Exception e) {
throw handleException(e);
} }
return checkNotNull(widgetTypeService.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, bundleAlias));
} }
@ApiOperation(value = "Get Widget Type (getWidgetType)", @ApiOperation(value = "Get Widget Type (getWidgetType)",
@ -231,20 +206,16 @@ public class WidgetTypeController extends AutoCommitController {
@RequestParam String bundleAlias, @RequestParam String bundleAlias,
@ApiParam(value = "Widget Type alias", required = true) @ApiParam(value = "Widget Type alias", required = true)
@RequestParam String alias) throws ThingsboardException { @RequestParam String alias) throws ThingsboardException {
try { TenantId tenantId;
TenantId tenantId; if (isSystem) {
if (isSystem) { tenantId = TenantId.fromUUID(ModelConstants.NULL_UUID);
tenantId = TenantId.fromUUID(ModelConstants.NULL_UUID); } else {
} else { tenantId = getCurrentUser().getTenantId();
tenantId = getCurrentUser().getTenantId();
}
WidgetType widgetType = widgetTypeService.findWidgetTypeByTenantIdBundleAliasAndAlias(tenantId, bundleAlias, alias);
checkNotNull(widgetType);
accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, Operation.READ, widgetType.getId(), widgetType);
return widgetType;
} catch (Exception e) {
throw handleException(e);
} }
WidgetType widgetType = widgetTypeService.findWidgetTypeByTenantIdBundleAliasAndAlias(tenantId, bundleAlias, alias);
checkNotNull(widgetType);
accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, Operation.READ, widgetType.getId(), widgetType);
return widgetType;
} }
} }

38
application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java

@ -74,12 +74,8 @@ public class WidgetsBundleController extends BaseController {
@ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException {
checkParameter("widgetsBundleId", strWidgetsBundleId); checkParameter("widgetsBundleId", strWidgetsBundleId);
try { WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); return checkWidgetsBundleId(widgetsBundleId, Operation.READ);
return checkWidgetsBundleId(widgetsBundleId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
} }
@ApiOperation(value = "Create Or Update Widget Bundle (saveWidgetsBundle)", @ApiOperation(value = "Create Or Update Widget Bundle (saveWidgetsBundle)",
@ -141,16 +137,12 @@ public class WidgetsBundleController extends BaseController {
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder) throws ThingsboardException {
try { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink));
return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink)); } else {
} else { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink));
return checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink));
}
} catch (Exception e) {
throw handleException(e);
} }
} }
@ -160,15 +152,11 @@ public class WidgetsBundleController extends BaseController {
@RequestMapping(value = "/widgetsBundles", method = RequestMethod.GET) @RequestMapping(value = "/widgetsBundles", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<WidgetsBundle> getWidgetsBundles() throws ThingsboardException { public List<WidgetsBundle> getWidgetsBundles() throws ThingsboardException {
try { if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { return checkNotNull(widgetsBundleService.findSystemWidgetsBundles(getTenantId()));
return checkNotNull(widgetsBundleService.findSystemWidgetsBundles(getTenantId())); } else {
} else { TenantId tenantId = getCurrentUser().getTenantId();
TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByTenantId(tenantId));
return checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByTenantId(tenantId));
}
} catch (Exception e) {
throw handleException(e);
} }
} }

9
application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java

@ -670,18 +670,19 @@ public final class EdgeGrpcSession implements Closeable {
} }
private void interruptPreviousSendDownlinkMsgsTask() { private void interruptPreviousSendDownlinkMsgsTask() {
log.info("[{}]Previous send downlink future was not properly completed, stopping it now!", this.sessionId); String msg = String.format("[%s] Previous send downlink future was not properly completed, stopping it now!", this.sessionId);
stopCurrentSendDownlinkMsgsTask(new RuntimeException()); stopCurrentSendDownlinkMsgsTask(new RuntimeException(msg));
} }
private void interruptGeneralProcessingOnSync(TenantId tenantId, EdgeId edgeId) { private void interruptGeneralProcessingOnSync(TenantId tenantId, EdgeId edgeId) {
log.info("[{}][{}][{}] Sync process started. General processing interrupted!", this.sessionId, tenantId, edgeId); String msg = String.format("[%s][%s] Sync process started. General processing interrupted!", tenantId, edgeId);
stopCurrentSendDownlinkMsgsTask(new RuntimeException()); stopCurrentSendDownlinkMsgsTask(new RuntimeException(msg));
} }
public void stopCurrentSendDownlinkMsgsTask(Exception e) { public void stopCurrentSendDownlinkMsgsTask(Exception e) {
if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()) { if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()) {
if (e != null) { if (e != null) {
log.debug(e.getMessage());
sessionState.getSendDownlinkMsgsFuture().setException(e); sessionState.getSendDownlinkMsgsFuture().setException(e);
} else { } else {
sessionState.getSendDownlinkMsgsFuture().set(null); sessionState.getSendDownlinkMsgsFuture().set(null);

9
application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java

@ -119,6 +119,15 @@ public class CustomerUserPermissions extends AbstractPermissions {
if (!Authority.CUSTOMER_USER.equals(userEntity.getAuthority())) { if (!Authority.CUSTOMER_USER.equals(userEntity.getAuthority())) {
return false; return false;
} }
if (!user.getCustomerId().equals(userEntity.getCustomerId())) {
return false;
}
if (Operation.READ.equals(operation)) {
return true;
}
return user.getId().equals(userId); return user.getId().equals(userId);
} }

23
application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java

@ -536,7 +536,19 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
protected MqttDeviceProfileTransportConfiguration createMqttDeviceProfileTransportConfiguration(TransportPayloadTypeConfiguration transportPayloadTypeConfiguration, boolean sendAckOnValidationException) { protected MqttDeviceProfileTransportConfiguration createMqttDeviceProfileTransportConfiguration(TransportPayloadTypeConfiguration transportPayloadTypeConfiguration, boolean sendAckOnValidationException) {
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration(); MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration();
mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(MqttTopics.DEVICE_TELEMETRY_TOPIC); mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(MqttTopics.DEVICE_TELEMETRY_TOPIC);
mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(MqttTopics.DEVICE_ATTRIBUTES_TOPIC); mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(MqttTopics.DEVICE_ATTRIBUTES_TOPIC);
mqttDeviceProfileTransportConfiguration.setDeviceAttributesSubscribeTopic(MqttTopics.DEVICE_ATTRIBUTES_TOPIC);
mqttDeviceProfileTransportConfiguration.setSendAckOnValidationException(sendAckOnValidationException);
mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration);
return mqttDeviceProfileTransportConfiguration;
}
protected MqttDeviceProfileTransportConfiguration createMqttDeviceProfileTransportConfiguration(TransportPayloadTypeConfiguration transportPayloadTypeConfiguration, boolean sendAckOnValidationException,
String telemetryTopic, String attributesPublishTopic, String attributesSubscribeTopic) {
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration();
mqttDeviceProfileTransportConfiguration.setDeviceTelemetryTopic(telemetryTopic);
mqttDeviceProfileTransportConfiguration.setDeviceAttributesTopic(attributesPublishTopic);
mqttDeviceProfileTransportConfiguration.setDeviceAttributesSubscribeTopic(attributesSubscribeTopic);
mqttDeviceProfileTransportConfiguration.setSendAckOnValidationException(sendAckOnValidationException); mqttDeviceProfileTransportConfiguration.setSendAckOnValidationException(sendAckOnValidationException);
mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration); mqttDeviceProfileTransportConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration);
return mqttDeviceProfileTransportConfiguration; return mqttDeviceProfileTransportConfiguration;
@ -798,6 +810,15 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
} }
public class EntityIdComparator<D extends EntityId> implements Comparator<D> {
@Override
public int compare(D o1, D o2) {
return o1.getId().compareTo(o2.getId());
}
}
protected static <T> ResultMatcher statusReason(Matcher<T> matcher) { protected static <T> ResultMatcher statusReason(Matcher<T> matcher) {
return jsonPath("$.message", matcher); return jsonPath("$.message", matcher);
} }

22
application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java

@ -945,6 +945,28 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController
Assert.assertEquals(savedDeviceProfile, foundDeviceProfile); Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
} }
@Test
public void testSaveDeviceProfileWorks() throws Exception {
JsonTransportPayloadConfiguration jsonTransportPayloadConfiguration = new JsonTransportPayloadConfiguration();
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration =
this.createMqttDeviceProfileTransportConfiguration(jsonTransportPayloadConfiguration, true,
"v1/devices/me/telemetry", "v1/devices/me/attributes", "v1/devices/me/subscribeattributes");
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile",
mqttDeviceProfileTransportConfiguration);
DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
Assert.assertNotNull(savedDeviceProfile);
Assert.assertEquals(savedDeviceProfile.getTransportType(), DeviceTransportType.MQTT);
Assert.assertTrue(savedDeviceProfile.getProfileData().getTransportConfiguration() instanceof MqttDeviceProfileTransportConfiguration);
MqttDeviceProfileTransportConfiguration transportConfiguration =
(MqttDeviceProfileTransportConfiguration) savedDeviceProfile.getProfileData().getTransportConfiguration();
Assert.assertTrue(transportConfiguration.isSendAckOnValidationException());
DeviceProfile foundDeviceProfile =
doGet("/api/deviceProfile/" + savedDeviceProfile.getId().getId().toString(), DeviceProfile.class);
Assert.assertEquals(savedDeviceProfile.getProfileData().getTransportConfiguration(),
foundDeviceProfile.getProfileData().getTransportConfiguration());
Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
}
private DeviceProfile testSaveDeviceProfileWithProtoPayloadType(String schema) throws Exception { private DeviceProfile testSaveDeviceProfileWithProtoPayloadType(String schema) throws Exception {
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = this.createProtoTransportPayloadConfiguration(schema, schema, null, null); ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = this.createProtoTransportPayloadConfiguration(schema, schema, null, null);
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = this.createMqttDeviceProfileTransportConfiguration(protoTransportPayloadConfiguration, false); MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = this.createMqttDeviceProfileTransportConfiguration(protoTransportPayloadConfiguration, false);

18
application/src/test/java/org/thingsboard/server/controller/BaseEntityQueryControllerTest.java

@ -145,6 +145,15 @@ public abstract class BaseEntityQueryControllerTest extends AbstractControllerTe
@Test @Test
public void testSysAdminCountEntitiesByQuery() throws Exception { public void testSysAdminCountEntitiesByQuery() throws Exception {
loginSysAdmin();
EntityTypeFilter allDeviceFilter = new EntityTypeFilter();
allDeviceFilter.setEntityType(EntityType.DEVICE);
EntityCountQuery query = new EntityCountQuery(allDeviceFilter);
Long initialCount = doPostWithResponse("/api/entitiesQuery/count", query, Long.class);
loginTenantAdmin();
List<Device> devices = new ArrayList<>(); List<Device> devices = new ArrayList<>();
for (int i = 0; i < 97; i++) { for (int i = 0; i < 97; i++) {
Device device = new Device(); Device device = new Device();
@ -184,13 +193,8 @@ public abstract class BaseEntityQueryControllerTest extends AbstractControllerTe
count = doPostWithResponse("/api/entitiesQuery/count", countQuery, Long.class); count = doPostWithResponse("/api/entitiesQuery/count", countQuery, Long.class);
Assert.assertEquals(97, count.longValue()); Assert.assertEquals(97, count.longValue());
EntityTypeFilter filter2 = new EntityTypeFilter(); Long count2 = doPostWithResponse("/api/entitiesQuery/count", query, Long.class);
filter2.setEntityType(EntityType.DEVICE); Assert.assertEquals(initialCount + 97, count2.longValue());
EntityCountQuery countQuery2 = new EntityCountQuery(filter2);
Long count2 = doPostWithResponse("/api/entitiesQuery/count", countQuery2, Long.class);
Assert.assertEquals(97, count2.longValue());
} }
@Test @Test

30
application/src/test/java/org/thingsboard/server/controller/BaseHomePageApiTest.java

@ -79,7 +79,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
//For system administrator //For system administrator
@Test @Test
public void testTenantsCountWsCmd() throws Exception { public void testTenantsCountWsCmd() throws Exception {
loginSysAdmin(); Long initialCount = getInitialEntityCount(EntityType.TENANT);
List<Tenant> tenants = new ArrayList<>(); List<Tenant> tenants = new ArrayList<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -94,7 +94,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
getWsClient().send(cmd); getWsClient().send(cmd);
EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply()); EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply());
Assert.assertEquals(1, update.getCmdId()); Assert.assertEquals(1, update.getCmdId());
Assert.assertEquals(101, update.getCount()); Assert.assertEquals(initialCount + 100, update.getCount());
for (Tenant tenant : tenants) { for (Tenant tenant : tenants) {
doDelete("/api/tenant/" + tenant.getId().toString()); doDelete("/api/tenant/" + tenant.getId().toString());
@ -103,7 +103,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
@Test @Test
public void testTenantProfilesCountWsCmd() throws Exception { public void testTenantProfilesCountWsCmd() throws Exception {
loginSysAdmin(); Long initialCount = getInitialEntityCount(EntityType.TENANT_PROFILE);
List<TenantProfile> tenantProfiles = new ArrayList<>(); List<TenantProfile> tenantProfiles = new ArrayList<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -118,7 +118,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
getWsClient().send(cmd); getWsClient().send(cmd);
EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply()); EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply());
Assert.assertEquals(1, update.getCmdId()); Assert.assertEquals(1, update.getCmdId());
Assert.assertEquals(101, update.getCount()); Assert.assertEquals(initialCount + 100, update.getCount());
for (TenantProfile tenantProfile : tenantProfiles) { for (TenantProfile tenantProfile : tenantProfiles) {
doDelete("/api/tenantProfile/" + tenantProfile.getId().toString()); doDelete("/api/tenantProfile/" + tenantProfile.getId().toString());
@ -127,7 +127,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
@Test @Test
public void testUsersCountWsCmd() throws Exception { public void testUsersCountWsCmd() throws Exception {
loginSysAdmin(); Long initialCount = getInitialEntityCount(EntityType.USER);
List<User> users = new ArrayList<>(); List<User> users = new ArrayList<>();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -144,7 +144,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
getWsClient().send(cmd); getWsClient().send(cmd);
EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply()); EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply());
Assert.assertEquals(1, update.getCmdId()); Assert.assertEquals(1, update.getCmdId());
Assert.assertEquals(103, update.getCount()); Assert.assertEquals(initialCount + 100, update.getCount());
for (User user : users) { for (User user : users) {
doDelete("/api/user/" + user.getId().toString()); doDelete("/api/user/" + user.getId().toString());
@ -153,6 +153,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
@Test @Test
public void testCustomersCountWsCmd() throws Exception { public void testCustomersCountWsCmd() throws Exception {
Long initialCount = getInitialEntityCount(EntityType.CUSTOMER);
loginTenantAdmin(); loginTenantAdmin();
List<Customer> customers = new ArrayList<>(); List<Customer> customers = new ArrayList<>();
@ -169,7 +170,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
getWsClient().send(cmd); getWsClient().send(cmd);
EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply()); EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply());
Assert.assertEquals(1, update.getCmdId()); Assert.assertEquals(1, update.getCmdId());
Assert.assertEquals(101, update.getCount()); Assert.assertEquals(initialCount + 100, update.getCount());
loginTenantAdmin(); loginTenantAdmin();
for (Customer customer : customers) { for (Customer customer : customers) {
@ -179,6 +180,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
@Test @Test
public void testDevicesCountWsCmd() throws Exception { public void testDevicesCountWsCmd() throws Exception {
Long initialCount = getInitialEntityCount(EntityType.DEVICE);
loginTenantAdmin(); loginTenantAdmin();
List<Device> devices = new ArrayList<>(); List<Device> devices = new ArrayList<>();
@ -195,7 +197,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
getWsClient().send(cmd); getWsClient().send(cmd);
EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply()); EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply());
Assert.assertEquals(1, update.getCmdId()); Assert.assertEquals(1, update.getCmdId());
Assert.assertEquals(100, update.getCount()); Assert.assertEquals(initialCount + 100, update.getCount());
loginTenantAdmin(); loginTenantAdmin();
for (Device device : devices) { for (Device device : devices) {
@ -205,6 +207,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
@Test @Test
public void testAssetsCountWsCmd() throws Exception { public void testAssetsCountWsCmd() throws Exception {
Long initialCount = getInitialEntityCount(EntityType.ASSET);
loginTenantAdmin(); loginTenantAdmin();
List<Asset> assets = new ArrayList<>(); List<Asset> assets = new ArrayList<>();
@ -221,7 +224,7 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
getWsClient().send(cmd); getWsClient().send(cmd);
EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply()); EntityCountUpdate update = getWsClient().parseCountReply(getWsClient().waitForReply());
Assert.assertEquals(1, update.getCmdId()); Assert.assertEquals(1, update.getCmdId());
Assert.assertEquals(100, update.getCount()); Assert.assertEquals(initialCount + 100, update.getCount());
loginTenantAdmin(); loginTenantAdmin();
for (Asset asset : assets) { for (Asset asset : assets) {
@ -431,6 +434,15 @@ public abstract class BaseHomePageApiTest extends AbstractControllerTest {
Assert.assertEquals(dashboards.size(), usageInfo.getDashboards()); Assert.assertEquals(dashboards.size(), usageInfo.getDashboards());
} }
private Long getInitialEntityCount(EntityType entityType) throws Exception {
loginSysAdmin();
EntityTypeFilter allEntityFilter = new EntityTypeFilter();
allEntityFilter.setEntityType(entityType);
EntityCountQuery query = new EntityCountQuery(allEntityFilter);
return doPostWithResponse("/api/entitiesQuery/count", query, Long.class);
}
private OAuth2Info createDefaultOAuth2Info() { private OAuth2Info createDefaultOAuth2Info() {
return new OAuth2Info(true, Lists.newArrayList( return new OAuth2Info(true, Lists.newArrayList(
OAuth2ParamsInfo.builder() OAuth2ParamsInfo.builder()

99
application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java

@ -32,11 +32,14 @@ import org.springframework.http.HttpHeaders;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.UserEmailInfo; import org.thingsboard.server.common.data.UserEmailInfo;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -57,7 +60,6 @@ import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@ -70,6 +72,8 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest {
private IdComparator<User> idComparator = new IdComparator<>(); private IdComparator<User> idComparator = new IdComparator<>();
private IdComparator<UserEmailInfo> userDataIdComparator = new IdComparator<>(); private IdComparator<UserEmailInfo> userDataIdComparator = new IdComparator<>();
private EntityIdComparator<UserId> userIdComparator = new EntityIdComparator<>();
private CustomerId customerNUULId = (CustomerId) createEntityId_NULL_UUID(new Customer()); private CustomerId customerNUULId = (CustomerId) createEntityId_NULL_UUID(new Customer());
@Autowired @Autowired
@ -651,6 +655,89 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest {
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
@Test
public void testGetUsersForAssign() throws Exception {
loginTenantAdmin();
String email = "testEmail1";
List<UserId> expectedCustomerUserIds = new ArrayList<>();
expectedCustomerUserIds.add(customerUserId);
for (int i = 0; i < 45; i++) {
User customerUser = createCustomerUser( customerId);
customerUser.setEmail(email + StringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)) + "@thingsboard.org");
User user = doPost("/api/user", customerUser, User.class);
expectedCustomerUserIds.add(user.getId());
}
List<UserId> expectedTenantUserIds = new ArrayList<>(List.copyOf(expectedCustomerUserIds));
expectedTenantUserIds.add(tenantAdminUserId);
Device device = new Device();
device.setName("testDevice");
Device savedDevice = doPost("/api/device", device, Device.class);
Alarm alarm = createTestAlarm(savedDevice);
List<UserId> loadedTenantUserIds = new ArrayList<>();
PageLink pageLink = new PageLink(33, 0);
PageData<UserEmailInfo> pageData;
do {
pageData = doGetTypedWithPageLink("/api/users/assign/" + alarm.getId().getId().toString() + "?",
new TypeReference<>() {}, pageLink);
loadedTenantUserIds.addAll(pageData.getData().stream().map(UserEmailInfo::getId)
.collect(Collectors.toList()));
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
Assert.assertEquals(1, loadedTenantUserIds.size());
Assert.assertEquals(tenantAdminUserId, loadedTenantUserIds.get(0));
doDelete("/api/alarm/" + alarm.getId().getId().toString());
savedDevice.setCustomerId(customerId);
savedDevice = doPost("/api/customer/" + customerId.getId()
+ "/device/" + savedDevice.getId().getId(), Device.class);
alarm = createTestAlarm(savedDevice);
List<UserId> loadedUserIds = new ArrayList<>();
pageLink = new PageLink(16, 0);
do {
pageData = doGetTypedWithPageLink("/api/users/assign/" + alarm.getId().getId().toString() + "?",
new TypeReference<>() {}, pageLink);
loadedUserIds.addAll(pageData.getData().stream().map(UserEmailInfo::getId)
.collect(Collectors.toList()));
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
expectedTenantUserIds.sort(userIdComparator);
loadedUserIds.sort(userIdComparator);
Assert.assertEquals(expectedTenantUserIds, loadedUserIds);
loginCustomerUser();
loadedUserIds = new ArrayList<>();
pageLink = new PageLink(16, 0);
do {
pageData = doGetTypedWithPageLink("/api/users/assign/" + alarm.getId().getId().toString() + "?",
new TypeReference<>() {}, pageLink);
loadedUserIds.addAll(pageData.getData().stream().map(UserEmailInfo::getId)
.collect(Collectors.toList()));
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
expectedCustomerUserIds.sort(userIdComparator);
loadedUserIds.sort(userIdComparator);
Assert.assertEquals(expectedCustomerUserIds, loadedUserIds);
}
@Test @Test
public void testDeleteUserWithDeleteRelationsOk() throws Exception { public void testDeleteUserWithDeleteRelationsOk() throws Exception {
loginSysAdmin(); loginSysAdmin();
@ -991,6 +1078,16 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest {
return loadedCustomerUsers; return loadedCustomerUsers;
} }
private Alarm createTestAlarm(Device device) {
Alarm alarm = new Alarm();
alarm.setOriginator(device.getId());
alarm.setCustomerId(device.getCustomerId());
alarm.setSeverity(AlarmSeverity.MAJOR);
alarm.setType("testAlarm");
alarm.setStartTs(System.currentTimeMillis());
return doPost("/api/alarm", alarm, Alarm.class);
}
@Test @Test
public void testEmptyDashboardSettings() throws Exception { public void testEmptyDashboardSettings() throws Exception {
loginCustomerUser(); loginCustomerUser();

21
application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/attributes/updates/MqttAttributesUpdatesIntegrationTest.java

@ -18,7 +18,11 @@ package org.thingsboard.server.transport.mqtt.mqttv3.attributes.updates;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.TransportPayloadType; import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.mqtt.MqttTestConfigProperties; import org.thingsboard.server.transport.mqtt.MqttTestConfigProperties;
import org.thingsboard.server.transport.mqtt.mqttv3.attributes.AbstractMqttAttributesIntegrationTest; import org.thingsboard.server.transport.mqtt.mqttv3.attributes.AbstractMqttAttributesIntegrationTest;
@ -46,6 +50,23 @@ public class MqttAttributesUpdatesIntegrationTest extends AbstractMqttAttributes
processJsonTestSubscribeToAttributesUpdates(DEVICE_ATTRIBUTES_TOPIC); processJsonTestSubscribeToAttributesUpdates(DEVICE_ATTRIBUTES_TOPIC);
} }
@Test
public void testJsonSubscribeToAttributesUpdatesFromTheServerOnCustomTopic() throws Exception {
Device tmp = savedDevice;
String customTopic = "v1/devices/me/subscribeattributes";
JsonTransportPayloadConfiguration jsonTransportPayloadConfiguration = new JsonTransportPayloadConfiguration();
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration =
this.createMqttDeviceProfileTransportConfiguration(jsonTransportPayloadConfiguration, true,
"v1/devices/me/telemetry", "v1/devices/me/attributes", customTopic);
DeviceProfile deviceProfile = this.createDeviceProfile("New device Profile",
mqttDeviceProfileTransportConfiguration);
DeviceProfile savedProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
savedDevice.setDeviceProfileId(savedProfile.getId());
doPost("/api/device", savedDevice);
processJsonTestSubscribeToAttributesUpdates(customTopic);
savedDevice = tmp;
}
@Test @Test
public void testJsonSubscribeToAttributesUpdatesFromTheServerOnShortTopic() throws Exception { public void testJsonSubscribeToAttributesUpdatesFromTheServerOnShortTopic() throws Exception {
processJsonTestSubscribeToAttributesUpdates(DEVICE_ATTRIBUTES_SHORT_TOPIC); processJsonTestSubscribeToAttributesUpdates(DEVICE_ATTRIBUTES_SHORT_TOPIC);

2
common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java

@ -77,6 +77,8 @@ public interface UserService extends EntityDaoService {
PageData<User> findCustomerUsers(TenantId tenantId, CustomerId customerId, PageLink pageLink); PageData<User> findCustomerUsers(TenantId tenantId, CustomerId customerId, PageLink pageLink);
PageData<User> findUsersByCustomerIds(TenantId tenantId, List<CustomerId> customerIds, PageLink pageLink);
void deleteCustomerUsers(TenantId tenantId, CustomerId customerId); void deleteCustomerUsers(TenantId tenantId, CustomerId customerId);
void setUserCredentialsEnabled(TenantId tenantId, UserId userId, boolean enabled); void setUserCredentialsEnabled(TenantId tenantId, UserId userId, boolean enabled);

3
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/MqttDeviceProfileTransportConfiguration.java

@ -28,6 +28,9 @@ public class MqttDeviceProfileTransportConfiguration implements DeviceProfileTra
private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC; private String deviceTelemetryTopic = MqttTopics.DEVICE_TELEMETRY_TOPIC;
@NoXss @NoXss
private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC; private String deviceAttributesTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
@NoXss
private String deviceAttributesSubscribeTopic = MqttTopics.DEVICE_ATTRIBUTES_TOPIC;
private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration; private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration;
private boolean sparkplug; private boolean sparkplug;
private Set<String> sparkplugAttributesMetricNames; private Set<String> sparkplugAttributesMetricNames;

2
common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java

@ -598,7 +598,7 @@ public class DefaultCoapClientContext implements CoapClientContext {
response.addMessageObserver(new TbCoapMessageObserver(requestId, id -> { response.addMessageObserver(new TbCoapMessageObserver(requestId, id -> {
TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(id); TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(id);
if (rpcRequestMsg != null) { if (rpcRequestMsg != null) {
transportService.process(state.getSession(), rpcRequestMsg, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); transportService.process(state.getSession(), rpcRequestMsg, RpcStatus.DELIVERED, true, TransportServiceCallback.EMPTY);
} }
}, id -> { }, id -> {
TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(id); TransportProtos.ToDeviceRpcRequestMsg rpcRequestMsg = transportContext.getRpcAwaitingAck().remove(id);

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/RpcDownlinkRequestCallbackProxy.java

@ -65,7 +65,7 @@ public abstract class RpcDownlinkRequestCallbackProxy<R, T> implements DownlinkR
@Override @Override
public void onSuccess(R request, T response) { public void onSuccess(R request, T response) {
transportService.process(client.getSession(), this.request, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); transportService.process(client.getSession(), this.request, RpcStatus.DELIVERED, true, TransportServiceCallback.EMPTY);
sendRpcReplyOnSuccess(response); sendRpcReplyOnSuccess(response);
if (callback != null) { if (callback != null) {
callback.onSuccess(request, response); callback.onSuccess(request, response);

1
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java

@ -177,6 +177,7 @@ public class MqttSslHandlerProvider {
} }
} }
if (credentialsBody == null) { if (credentialsBody == null) {
log.debug("Failed to find credentials for device certificate chain: {}", chain);
throw new CertificateException("Invalid Device Certificate"); throw new CertificateException("Invalid Device Certificate");
} }
} }

7
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java

@ -322,7 +322,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
int msgId = ((MqttPubAckMessage) msg).variableHeader().messageId(); int msgId = ((MqttPubAckMessage) msg).variableHeader().messageId();
TransportProtos.ToDeviceRpcRequestMsg rpcRequest = rpcAwaitingAck.remove(msgId); TransportProtos.ToDeviceRpcRequestMsg rpcRequest = rpcAwaitingAck.remove(msgId);
if (rpcRequest != null) { if (rpcRequest != null) {
transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.DELIVERED, TransportServiceCallback.EMPTY); transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest, RpcStatus.DELIVERED, true, TransportServiceCallback.EMPTY);
} }
break; break;
default: default:
@ -687,6 +687,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
for (MqttTopicSubscription subscription : mqttMsg.payload().topicSubscriptions()) { for (MqttTopicSubscription subscription : mqttMsg.payload().topicSubscriptions()) {
String topic = subscription.topicName(); String topic = subscription.topicName();
MqttQoS reqQoS = subscription.qualityOfService(); MqttQoS reqQoS = subscription.qualityOfService();
if (deviceSessionCtx.isDeviceSubscriptionAttributesTopic(topic)){
processAttributesSubscribe(grantedQoSList, topic, reqQoS, TopicType.V1);
activityReported = true;
continue;
}
try { try {
if (sparkplugSessionHandler != null) { if (sparkplugSessionHandler != null) {
sparkplugSessionHandler.handleSparkplugSubscribeMsg(grantedQoSList, subscription, reqQoS); sparkplugSessionHandler.handleSparkplugSubscribeMsg(grantedQoSList, subscription, reqQoS);

14
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java

@ -80,7 +80,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
private MqttVersion mqttVersion; private MqttVersion mqttVersion;
private volatile MqttTopicFilter telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); private volatile MqttTopicFilter telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter();
private volatile MqttTopicFilter attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); private volatile MqttTopicFilter attributesPublishTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter();
private volatile MqttTopicFilter attributesSubscribeTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter();
private volatile TransportPayloadType payloadType = TransportPayloadType.JSON; private volatile TransportPayloadType payloadType = TransportPayloadType.JSON;
private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor; private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor;
private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor; private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor;
@ -110,7 +111,11 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
} }
public boolean isDeviceAttributesTopic(String topicName) { public boolean isDeviceAttributesTopic(String topicName) {
return attributesTopicFilter.filter(topicName); return attributesPublishTopicFilter.filter(topicName);
}
public boolean isDeviceSubscriptionAttributesTopic(String topicName) {
return attributesSubscribeTopicFilter.filter(topicName);
} }
public MqttTransportAdaptor getPayloadAdaptor() { public MqttTransportAdaptor getPayloadAdaptor() {
@ -161,7 +166,8 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttConfig.getTransportPayloadTypeConfiguration(); TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = mqttConfig.getTransportPayloadTypeConfiguration();
payloadType = transportPayloadTypeConfiguration.getTransportPayloadType(); payloadType = transportPayloadTypeConfiguration.getTransportPayloadType();
telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic()); telemetryTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceTelemetryTopic());
attributesTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic()); attributesPublishTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesTopic());
attributesSubscribeTopicFilter = MqttTopicFilterFactory.toFilter(mqttConfig.getDeviceAttributesSubscribeTopic());
sendAckOnValidationException = mqttConfig.isSendAckOnValidationException(); sendAckOnValidationException = mqttConfig.isSendAckOnValidationException();
if (TransportPayloadType.PROTOBUF.equals(payloadType)) { if (TransportPayloadType.PROTOBUF.equals(payloadType)) {
ProtoTransportPayloadConfiguration protoTransportPayloadConfig = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration; ProtoTransportPayloadConfiguration protoTransportPayloadConfig = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
@ -171,7 +177,7 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext {
} }
} else { } else {
telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter();
attributesTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); attributesPublishTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter();
payloadType = TransportPayloadType.JSON; payloadType = TransportPayloadType.JSON;
sendAckOnValidationException = false; sendAckOnValidationException = false;
} }

2
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java

@ -117,6 +117,8 @@ public interface TransportService {
void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback); void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback);
void process(SessionInfoProto sessionInfo, ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, boolean reportActivity, TransportServiceCallback<Void> callback);
void process(SessionInfoProto sessionInfo, ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback); void process(SessionInfoProto sessionInfo, ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback);
void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback); void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback);

9
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java

@ -647,6 +647,11 @@ public class DefaultTransportService implements TransportService {
@Override @Override
public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback) { public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback) {
process(sessionInfo, msg, rpcStatus, false, callback);
}
@Override
public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, boolean reportActivity, TransportServiceCallback<Void> callback) {
TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg = TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder() TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg = TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder()
.setRequestId(msg.getRequestId()) .setRequestId(msg.getRequestId())
.setRequestIdLSB(msg.getRequestIdLSB()) .setRequestIdLSB(msg.getRequestIdLSB())
@ -655,7 +660,9 @@ public class DefaultTransportService implements TransportService {
.build(); .build();
if (checkLimits(sessionInfo, responseMsg, callback)) { if (checkLimits(sessionInfo, responseMsg, callback)) {
reportActivityInternal(sessionInfo); if (reportActivity) {
reportActivityInternal(sessionInfo);
}
sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setRpcResponseStatusMsg(responseMsg).build(), sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setRpcResponseStatusMsg(responseMsg).build(),
new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY)); new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY));
} }

12
dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java

@ -20,6 +20,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
@ -102,6 +103,17 @@ public class JpaUserDao extends JpaAbstractSearchTextDao<UserEntity, User> imple
} }
@Override
public PageData<User> findUsersByCustomerIds(UUID tenantId, List<CustomerId> customerIds, PageLink pageLink) {
return DaoUtil.toPageData(
userRepository
.findTenantAndCustomerUsers(
tenantId,
DaoUtil.toUUIDs(customerIds),
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override @Override
public PageData<User> findAll(PageLink pageLink) { public PageData<User> findAll(PageLink pageLink) {
return DaoUtil.toPageData(userRepository.findAll(DaoUtil.toPageable(pageLink))); return DaoUtil.toPageData(userRepository.findAll(DaoUtil.toPageable(pageLink)));

8
dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java

@ -44,6 +44,14 @@ public interface UserRepository extends JpaRepository<UserEntity, UUID> {
@Param("authority") Authority authority, @Param("authority") Authority authority,
Pageable pageable); Pageable pageable);
@Query("SELECT u FROM UserEntity u WHERE u.tenantId = :tenantId " +
"AND u.customerId IN (:customerIds) " +
"AND LOWER(u.searchText) LIKE LOWER(CONCAT('%', :searchText, '%'))")
Page<UserEntity> findTenantAndCustomerUsers(@Param("tenantId") UUID tenantId,
@Param("customerIds") Collection<UUID> customerIds,
@Param("searchText") String searchText,
Pageable pageable);
@Query("SELECT u FROM UserEntity u WHERE u.tenantId = :tenantId " + @Query("SELECT u FROM UserEntity u WHERE u.tenantId = :tenantId " +
"AND LOWER(u.searchText) LIKE LOWER(CONCAT('%', :searchText, '%'))") "AND LOWER(u.searchText) LIKE LOWER(CONCAT('%', :searchText, '%'))")
Page<UserEntity> findByTenantId(@Param("tenantId") UUID tenantId, Page<UserEntity> findByTenantId(@Param("tenantId") UUID tenantId,

11
dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.user; package org.thingsboard.server.dao.user;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
@ -82,6 +83,16 @@ public interface UserDao extends Dao<User>, TenantEntityDao {
*/ */
PageData<User> findCustomerUsers(UUID tenantId, UUID customerId, PageLink pageLink); PageData<User> findCustomerUsers(UUID tenantId, UUID customerId, PageLink pageLink);
/**
* Find users for alarm assignment by tenantId, customerId and page link.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param pageLink the page link
* @return the list of user entities
*/
PageData<User> findUsersByCustomerIds(UUID tenantId, List<CustomerId> customerIds, PageLink pageLink);
PageData<User> findAll(PageLink pageLink); PageData<User> findAll(PageLink pageLink);
PageData<User> findAllByAuthority(Authority authority, PageLink pageLink); PageData<User> findAllByAuthority(Authority authority, PageLink pageLink);

9
dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java

@ -296,6 +296,15 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
return userDao.findCustomerUsers(tenantId.getId(), customerId.getId(), pageLink); return userDao.findCustomerUsers(tenantId.getId(), customerId.getId(), pageLink);
} }
@Override
public PageData<User> findUsersByCustomerIds(TenantId tenantId, List<CustomerId> customerIds, PageLink pageLink) {
log.trace("Executing findTenantAndCustomerUsers, tenantId [{}], customerIds [{}], pageLink [{}]", tenantId, customerIds, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validatePageLink(pageLink);
customerIds.forEach(customerId -> {validateId(customerId, "Incorrect customerId " + customerId);});
return userDao.findUsersByCustomerIds(tenantId.getId(), customerIds, pageLink);
}
@Override @Override
public void deleteCustomerUsers(TenantId tenantId, CustomerId customerId) { public void deleteCustomerUsers(TenantId tenantId, CustomerId customerId) {
log.trace("Executing deleteCustomerUsers, customerId [{}]", customerId); log.trace("Executing deleteCustomerUsers, customerId [{}]", customerId);

14
rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java

@ -65,6 +65,7 @@ import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.data.UpdateMessage;
import org.thingsboard.server.common.data.UsageInfo; import org.thingsboard.server.common.data.UsageInfo;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.UserEmailInfo;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo;
@ -2628,6 +2629,19 @@ public class RestClient implements Closeable {
}, params).getBody(); }, params).getBody();
} }
public PageData<UserEmailInfo> getUsersForAssign(AlarmId alarmId, PageLink pageLink) {
Map<String, String> params = new HashMap<>();
params.put("alarmId", alarmId.getId().toString());
addPageLinkToParam(params, pageLink);
return restTemplate.exchange(
baseURL + "/users/assign/{alarmId}" + getUrlParams(pageLink),
HttpMethod.GET,
HttpEntity.EMPTY,
new ParameterizedTypeReference<PageData<UserEmailInfo>>() {
}, params).getBody();
}
public void setUserCredentialsEnabled(UserId userId, boolean userCredentialsEnabled) { public void setUserCredentialsEnabled(UserId userId, boolean userCredentialsEnabled) {
restTemplate.postForLocation( restTemplate.postForLocation(
baseURL + "/api/user/{userId}/userCredentialsEnabled?userCredentialsEnabled={userCredentialsEnabled}", baseURL + "/api/user/{userId}/userCredentialsEnabled?userCredentialsEnabled={userCredentialsEnabled}",

16
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java

@ -35,7 +35,6 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory;
import org.springframework.http.client.Netty4ClientHttpRequestFactory; import org.springframework.http.client.Netty4ClientHttpRequestFactory;
import org.thingsboard.server.common.data.StringUtils;
import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback; import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate; import org.springframework.web.client.AsyncRestTemplate;
@ -49,6 +48,7 @@ import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.rule.engine.credentials.BasicCredentials; import org.thingsboard.rule.engine.credentials.BasicCredentials;
import org.thingsboard.rule.engine.credentials.ClientCredentials; import org.thingsboard.rule.engine.credentials.ClientCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType; import org.thingsboard.rule.engine.credentials.CredentialsType;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
@ -192,7 +192,7 @@ public class TbHttpClient {
config.isIgnoreRequestBody()) { config.isIgnoreRequestBody()) {
entity = new HttpEntity<>(headers); entity = new HttpEntity<>(headers);
} else { } else {
entity = new HttpEntity<>(msg.getData(), headers); entity = new HttpEntity<>(getData(msg), headers);
} }
URI uri = buildEncodedUri(endpointUrl); URI uri = buildEncodedUri(endpointUrl);
@ -243,6 +243,18 @@ public class TbHttpClient {
return uri; return uri;
} }
private String getData(TbMsg msg) {
String data = msg.getData();
if (config.isTrimDoubleQuotes()) {
final String dataBefore = data;
data = data.replaceAll("^\"|\"$", "");;
log.trace("Trimming double quotes. Before trim: [{}], after trim: [{}]", dataBefore, data);
}
return data;
}
private TbMsg processResponse(TbContext ctx, TbMsg origMsg, ResponseEntity<String> response) { private TbMsg processResponse(TbContext ctx, TbMsg origMsg, ResponseEntity<String> response) {
TbMsgMetaData metaData = origMsg.getMetaData(); TbMsgMetaData metaData = origMsg.getMetaData();
metaData.putValue(STATUS, response.getStatusCode().name()); metaData.putValue(STATUS, response.getStatusCode().name());

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeConfiguration.java

@ -37,8 +37,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration<TbRestA
private int readTimeoutMs; private int readTimeoutMs;
private int maxParallelRequestsCount; private int maxParallelRequestsCount;
private boolean useRedisQueueForMsgPersistence; private boolean useRedisQueueForMsgPersistence;
private boolean trimQueue; private boolean trimDoubleQuotes;
private int maxQueueSize;
private boolean enableProxy; private boolean enableProxy;
private boolean useSystemProxyProperties; private boolean useSystemProxyProperties;
private String proxyHost; private String proxyHost;
@ -59,7 +58,7 @@ public class TbRestApiCallNodeConfiguration implements NodeConfiguration<TbRestA
configuration.setReadTimeoutMs(0); configuration.setReadTimeoutMs(0);
configuration.setMaxParallelRequestsCount(0); configuration.setMaxParallelRequestsCount(0);
configuration.setUseRedisQueueForMsgPersistence(false); configuration.setUseRedisQueueForMsgPersistence(false);
configuration.setTrimQueue(false); configuration.setTrimDoubleQuotes(false);
configuration.setEnableProxy(false); configuration.setEnableProxy(false);
configuration.setCredentials(new AnonymousCredentials()); configuration.setCredentials(new AnonymousCredentials());
configuration.setIgnoreRequestBody(false); configuration.setIgnoreRequestBody(false);

6
ui-ngx/src/app/core/http/user.service.ts

@ -51,6 +51,12 @@ export class UserService {
defaultHttpOptionsFromConfig(config)); defaultHttpOptionsFromConfig(config));
} }
public getUsersForAssign(alarmId: string, pageLink: PageLink,
config?: RequestConfig): Observable<PageData<UserEmailInfo>> {
return this.http.get<PageData<UserEmailInfo>>(`/api/users/assign/${alarmId}${pageLink.toQuery()}`,
defaultHttpOptionsFromConfig(config));
}
public getUser(userId: string, config?: RequestConfig): Observable<User> { public getUser(userId: string, config?: RequestConfig): Observable<User> {
return this.http.get<User>(`/api/user/${userId}`, defaultHttpOptionsFromConfig(config)); return this.http.get<User>(`/api/user/${userId}`, defaultHttpOptionsFromConfig(config));
} }

3
ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.html

@ -25,8 +25,7 @@
<mat-autocomplete class="tb-assignee-autocomplete" <mat-autocomplete class="tb-assignee-autocomplete"
#userAutocomplete="matAutocomplete" #userAutocomplete="matAutocomplete"
[displayWith]="displayUserFn" [displayWith]="displayUserFn"
(optionSelected)="selected($event)" (optionSelected)="selected($event)">
panelWidth="260px">
<mat-option [fxHide]="!assigneeId" [value]="null"> <mat-option [fxHide]="!assigneeId" [value]="null">
<mat-icon class="unassigned-icon">account_circle</mat-icon> <mat-icon class="unassigned-icon">account_circle</mat-icon>
<span translate>alarm.unassigned</span> <span translate>alarm.unassigned</span>

12
ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.scss

@ -17,7 +17,7 @@
:host { :host {
width: 100%; width: 100%;
overflow: auto; overflow: auto;
background: #fff; background: white;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15); box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3), 0px 2px 6px 2px rgba(0, 0, 0, 0.15);
border-radius: 4px; border-radius: 4px;
} }
@ -27,7 +27,7 @@
padding: 8px; padding: 8px;
height: 340px; height: 340px;
font-size: 14px; font-size: 14px;
background-color: #fff; background-color: white;
} }
.mat-form-field-appearance-outline .mdc-notched-outline__trailing{ .mat-form-field-appearance-outline .mdc-notched-outline__trailing{
@ -37,7 +37,6 @@
.tb-assignee-autocomplete { .tb-assignee-autocomplete {
&.tb-assignee-autocomplete.mat-mdc-autocomplete-panel { &.tb-assignee-autocomplete.mat-mdc-autocomplete-panel {
position: relative; position: relative;
left: -8px;
margin-top: 8px; margin-top: 8px;
box-shadow: none !important; box-shadow: none !important;
} }
@ -58,17 +57,16 @@
align-items: center; align-items: center;
margin-right: 8px; margin-right: 8px;
border-radius: 50%; border-radius: 50%;
background-color: #5cb445;
width: 28px; width: 28px;
height: 28px; height: 28px;
min-width: 28px; min-width: 28px;
min-height: 28px; min-height: 28px;
color: #fff; color: white;
font-size: 13px; font-size: 13px;
font-weight: 700 font-weight: 700
} }
.user-display-name { .user-display-name {
max-width: 180px; max-width: 80%;
overflow: hidden; overflow: hidden;
span { span {
overflow: hidden; overflow: hidden;
@ -79,8 +77,8 @@
} }
} }
.mdc-list-item__primary-text { .mdc-list-item__primary-text {
width: 100%;
display: flex; display: flex;
justify-content: start;
align-items: center; align-items: center;
line-height: normal; line-height: normal;
} }

14
ui-ngx/src/app/modules/home/components/alarm/alarm-assignee-panel.component.ts

@ -65,6 +65,8 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
assigneeId?: string; assigneeId?: string;
reassigned: boolean = false;
selectUserFormGroup: FormGroup; selectUserFormGroup: FormGroup;
@ViewChild('userInput', {static: true}) userInput: ElementRef; @ViewChild('userInput', {static: true}) userInput: ElementRef;
@ -130,12 +132,18 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
assign(user: User): void { assign(user: User): void {
this.alarmService.assignAlarm(this.alarmId, user.id.id, {ignoreLoading: true}).subscribe( this.alarmService.assignAlarm(this.alarmId, user.id.id, {ignoreLoading: true}).subscribe(
() => this.overlayRef.dispose()); () => {
this.reassigned = true;
this.overlayRef.dispose()
});
} }
unassign(): void { unassign(): void {
this.alarmService.unassignAlarm(this.alarmId, {ignoreLoading: true}).subscribe( this.alarmService.unassignAlarm(this.alarmId, {ignoreLoading: true}).subscribe(
() => this.overlayRef.dispose()); () => {
this.reassigned = true;
this.overlayRef.dispose()
});
} }
fetchUsers(searchText?: string): Observable<Array<UserEmailInfo>> { fetchUsers(searchText?: string): Observable<Array<UserEmailInfo>> {
@ -144,7 +152,7 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
property: 'email', property: 'email',
direction: Direction.ASC direction: Direction.ASC
}); });
return this.userService.findUsersByQuery(pageLink, {ignoreLoading: true}) return this.userService.getUsersForAssign(this.alarmId, pageLink, {ignoreLoading: true})
.pipe( .pipe(
catchError(() => of(emptyPageData<UserEmailInfo>())), catchError(() => of(emptyPageData<UserEmailInfo>())),
map(pageData => { map(pageData => {

35
ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.html

@ -16,28 +16,15 @@
--> -->
<div class="tb-assignee" fxLayout="row" fxLayoutAlign="start center" <mat-form-field fxFlex class="mat-block" style="margin-bottom: 25px"
(click)="openAlarmAssigneePanel($event, alarm)"> (click)="openAlarmAssigneePanel($event, alarm)"
<span *ngIf="alarm?.assigneeId" class="assigned-container"> subscriptSizing="dynamic">
<span class="user-avatar" [style.backgroundColor]="getAvatarBgColor(alarm.assignee)"> <mat-label translate>alarm.assignee</mat-label>
{{ getUserInitials(alarm.assignee) }} <input matInput readonly [value]="getAssignee()">
</span> <span *ngIf="alarm?.assigneeId" matPrefix class="user-avatar"
<span [matTooltip]="getUserDisplayName(alarm.assignee)" [style.backgroundColor]="getAvatarBgColor(alarm.assignee)">
matTooltipPosition="above" {{ getUserInitials(alarm.assignee) }}
style="text-overflow: ellipsis">
{{ getUserDisplayName(alarm.assignee) }}
</span>
</span> </span>
<span *ngIf="!alarm?.assigneeId" class="unassigned-container" fxLayout="row" fxLayoutAlign="start center"> <mat-icon *ngIf="!alarm?.assigneeId" matPrefix class="unassigned-icon">account_circle</mat-icon>
<mat-icon class="material-icons unassigned-icon">account_circle</mat-icon> <mat-icon matSuffix>arrow_drop_down</mat-icon>
<span translate>alarm.unassigned</span> </mat-form-field>
</span>
<button fxFlexAlign="flex-end"
mat-icon-button
matTooltip="{{ 'alarm.assign' | translate }}"
matTooltipPosition="above">
<mat-icon>
keyboard_arrow_down
</mat-icon>
</button>
</div>

55
ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss

@ -14,36 +14,29 @@
* limitations under the License. * limitations under the License.
*/ */
:host { .user-avatar {
.tb-assignee { display: inline-flex;
cursor: pointer; justify-content: center;
max-width: 273px; align-items: center;
border-radius: 50%;
.assigned-container { width: 28px;
overflow: hidden; height: 28px;
white-space: nowrap; min-width: 28px;
text-overflow: ellipsis; min-height: 28px;
color: white;
font-size: 13px;
font-weight: 700;
margin-left: 12px;
margin-right: 20px;
}
.user-avatar { .unassigned-icon {
display: inline-flex; width: 28px;
justify-content: center; height: 28px;
align-items: center; font-size: 28px;
border-radius: 50%; color: rgba(0, 0, 0, 0.38);
width: 28px; overflow: visible;
height: 28px; margin-left: 12px;
min-width: 28px; margin-right: 20px;
min-height: 28px; padding: 0;
color: white;
font-size: 13px;
font-weight: 700;
}
}
.material-icons.unassigned-icon {
width: 28px;
height: 28px;
font-size: 28px;
color: rgba(0, 0, 0, 0.38);
overflow: visible;
}
}
} }

92
ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts

@ -14,17 +14,17 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { Component, EventEmitter, Injector, Input, Output, StaticProvider, ViewContainerRef } from '@angular/core';
Component, EventEmitter, Injector, Input, Output, StaticProvider, ViewContainerRef
} from '@angular/core';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { AlarmAssignee, AlarmInfo } from '@shared/models/alarm.models'; import { AlarmAssignee, AlarmInfo } from '@shared/models/alarm.models';
import { import {
ALARM_ASSIGNEE_PANEL_DATA, AlarmAssigneePanelComponent, ALARM_ASSIGNEE_PANEL_DATA,
AlarmAssigneePanelComponent,
AlarmAssigneePanelData AlarmAssigneePanelData
} from '@home/components/alarm/alarm-assignee-panel.component'; } from '@home/components/alarm/alarm-assignee-panel.component';
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'; import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentPortal } from '@angular/cdk/portal';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'tb-alarm-assignee', selector: 'tb-alarm-assignee',
@ -35,12 +35,26 @@ export class AlarmAssigneeComponent {
@Input() @Input()
alarm: AlarmInfo; alarm: AlarmInfo;
@Input()
allowAssign: boolean;
@Output() @Output()
alarmReassigned = new EventEmitter<boolean>(); alarmReassigned = new EventEmitter<boolean>();
constructor(private utilsService: UtilsService, constructor(private utilsService: UtilsService,
private overlay: Overlay, private overlay: Overlay,
private viewContainerRef: ViewContainerRef) { private viewContainerRef: ViewContainerRef,
private translateService: TranslateService) {
}
getAssignee() {
if (this.alarm) {
if (this.alarm.assignee) {
return this.getUserDisplayName(this.alarm.assignee);
} else {
return this.translateService.instant('alarm.unassigned');
}
}
} }
getUserDisplayName(entity: AlarmAssignee) { getUserDisplayName(entity: AlarmAssignee) {
@ -103,39 +117,41 @@ export class AlarmAssigneeComponent {
if ($event) { if ($event) {
$event.stopPropagation(); $event.stopPropagation();
} }
const target = $event.target || $event.srcElement || $event.currentTarget; if (this.allowAssign) {
const config = new OverlayConfig(); const target = $event.currentTarget;
config.backdropClass = 'cdk-overlay-transparent-backdrop'; const config = new OverlayConfig();
config.hasBackdrop = true; config.backdropClass = 'cdk-overlay-transparent-backdrop';
const connectedPosition: ConnectedPosition = { config.hasBackdrop = true;
originX: 'end', const connectedPosition: ConnectedPosition = {
originY: 'bottom', originX: 'center',
overlayX: 'end', originY: 'bottom',
overlayY: 'top' overlayX: 'center',
}; overlayY: 'top'
config.positionStrategy = this.overlay.position().flexibleConnectedTo(target as HTMLElement) };
.withPositions([connectedPosition]); config.positionStrategy = this.overlay.position().flexibleConnectedTo(target as HTMLElement)
config.minWidth = '260px'; .withPositions([connectedPosition]);
const overlayRef = this.overlay.create(config); config.width = (target as HTMLElement).offsetWidth;
overlayRef.backdropClick().subscribe(() => { const overlayRef = this.overlay.create(config);
overlayRef.dispose(); overlayRef.backdropClick().subscribe(() => {
}); overlayRef.dispose();
const providers: StaticProvider[] = [ });
{ const providers: StaticProvider[] = [
provide: ALARM_ASSIGNEE_PANEL_DATA, {
useValue: { provide: ALARM_ASSIGNEE_PANEL_DATA,
alarmId: alarm.id.id, useValue: {
assigneeId: alarm.assigneeId?.id alarmId: alarm.id.id,
} as AlarmAssigneePanelData assigneeId: alarm.assigneeId?.id
}, } as AlarmAssigneePanelData
{ },
provide: OverlayRef, {
useValue: overlayRef provide: OverlayRef,
} useValue: overlayRef
]; }
const injector = Injector.create({parent: this.viewContainerRef.injector, providers}); ];
overlayRef.attach(new ComponentPortal(AlarmAssigneePanelComponent, const injector = Injector.create({parent: this.viewContainerRef.injector, providers});
this.viewContainerRef, injector)).onDestroy(() => this.alarmReassigned.emit(true)); overlayRef.attach(new ComponentPortal(AlarmAssigneePanelComponent,
this.viewContainerRef, injector)).onDestroy(() => this.alarmReassigned.emit(true));
}
} }
} }

17
ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.html

@ -17,11 +17,8 @@
--> -->
<div style="min-width: 600px;"> <div style="min-width: 600px;">
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<h2>{{ 'alarm.comments' | translate }}</h2>
<span fxFlex></span> <span fxFlex></span>
<button mat-icon-button <button mat-icon-button (click)="close()" type="button">
(click)="close()"
type="button">
<mat-icon class="material-icons">close</mat-icon> <mat-icon class="material-icons">close</mat-icon>
</button> </button>
</mat-toolbar> </mat-toolbar>
@ -29,16 +26,8 @@
</mat-progress-bar> </mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content style="padding: 0"> <div mat-dialog-content style="padding: 0">
<tb-alarm-comment #alarmCommentComponent [alarmId]="alarmId" <tb-alarm-comment [alarmId]="alarmId"
[commentsHeaderEnabled]="commentsHeaderEnabled"> [alarmActivityOnly]="true">
</tb-alarm-comment> </tb-alarm-comment>
</div> </div>
<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end">
<button mat-raised-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="close()" cdkFocusInitial>
{{ 'action.close' | translate }}
</button>
</div>
</div> </div>

4
ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.ts

@ -25,7 +25,6 @@ import { AlarmInfo } from '@shared/models/alarm.models';
export interface AlarmCommentDialogData { export interface AlarmCommentDialogData {
alarmId?: string; alarmId?: string;
alarm?: AlarmInfo; alarm?: AlarmInfo;
commentsHeaderEnabled: boolean;
} }
@Component({ @Component({
@ -37,14 +36,11 @@ export class AlarmCommentDialogComponent extends DialogComponent<AlarmCommentDia
alarmId: string; alarmId: string;
commentsHeaderEnabled: boolean = false;
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: AlarmCommentDialogData, @Inject(MAT_DIALOG_DATA) public data: AlarmCommentDialogData,
public dialogRef: MatDialogRef<AlarmCommentDialogComponent, void>) { public dialogRef: MatDialogRef<AlarmCommentDialogComponent, void>) {
super(store, router, dialogRef); super(store, router, dialogRef);
this.commentsHeaderEnabled = this.data.commentsHeaderEnabled
this.alarmId = this.data.alarmId; this.alarmId = this.data.alarmId;
} }

247
ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.html

@ -17,129 +17,147 @@
--> -->
<div [formGroup]="alarmCommentFormGroup" class="tb-alarm-comments" fxLayout="column"> <div [formGroup]="alarmCommentFormGroup" class="tb-alarm-comments" fxLayout="column">
<div class="tb-alarm-comments-header" fxLayout="row" fxLayoutAlign="space-between baseline"> <div class="header" [ngClass]="{'activity-only': alarmActivityOnly}">
<span *ngIf="commentsHeaderEnabled" class="tb-alarm-comments-header-title"> <div class="header-container" fxLayout="row" fxLayoutAlign="space-between center"
{{ 'alarm-comment.comments' | translate }} [ngClass]="{'asc': isDirectionAscending(), 'activity-only': alarmActivityOnly}">
</span> <span class="header-title" translate>
<div style="margin-left: auto"> alarm-activity.activity
<button mat-icon-button </span>
type="button" <div style="margin-left: auto">
(click)="changeSortDirection()" <button mat-icon-button
matTooltip="{{ 'alarm-comment.sort-direction' | translate }}" type="button"
matTooltipPosition="above"> (click)="exportAlarmActivity()"
<mat-icon class="material-icons">{{ getSortDirectionIcon() }}</mat-icon> matTooltip="{{ 'alarm-activity.export' | translate }}"
</button> matTooltipPosition="above">
<button mat-icon-button <mat-icon class="material-icons" svgIcon="mdi:file-export"></mat-icon>
type="button" </button>
(click)="loadAlarmComments()" <button mat-icon-button
matTooltip="{{ 'alarm-comment.refresh' | translate }}" type="button"
matTooltipPosition="above"> (click)="changeSortDirection()"
<mat-icon class="material-icons">refresh</mat-icon> [matTooltip]="getSortDirectionTooltipText()"
</button> matTooltipPosition="above">
<mat-icon class="material-icons" [svgIcon]="getSortDirectionIcon()"></mat-icon>
</button>
<button mat-icon-button
type="button"
(click)="loadAlarmComments()"
matTooltip="{{ 'alarm-activity.refresh' | translate }}"
matTooltipPosition="above">
<mat-icon class="material-icons">refresh</mat-icon>
</button>
</div>
</div> </div>
</div> </div>
<div fxLayout="column" fxLayoutGap="32px"> <div fxLayout="column">
<ng-container *ngIf="isDirectionDescending()"> <ng-container *ngIf="!isDirectionAscending()">
<ng-container *ngTemplateOutlet="commentInput"></ng-container> <ng-container *ngTemplateOutlet="commentInput"></ng-container>
</ng-container> </ng-container>
<div fxFlex *ngFor="let displayDataElement of displayData; index as i"> <div class="comments-container" fxLayout="column" fxLayoutGap="12px" style="padding: 24px"
<div style="margin-left: 38px" [ngClass]="{'asc': isDirectionAscending(), 'activity-only': alarmActivityOnly}">
*ngIf="displayDataElement.isSystemComment; else userComment"> <div fxFlex *ngFor="let displayDataElement of displayData; index as i">
<span class="tb-alarm-comments-system-text" <div class="system-comment" *ngIf="displayDataElement.isSystemComment; else userComment">
style="margin-right: 8px"> <span class="system-text" style="margin-right: 8px">
{{ displayDataElement.commentText }} {{ displayDataElement.commentText }}
</span> </span>
<span class="tb-alarm-comments-time"> <span class="time" style="padding: 3px"
{{ displayDataElement.createdDateAgo }} [matTooltip]="displayDataElement.createdTime"
</span> matTooltipPosition="right">
</div> {{ displayDataElement.createdDateAgo }}
<ng-template #userComment> </span>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"
*ngIf="!displayDataElement.edit; else commentEditing"
(mouseenter)="onCommentMouseEnter(displayDataElement.commentId, i)"
(mouseleave)="onCommentMouseLeave(i)">
<div fxLayout="row" fxLayoutAlign="center center" fxFlexAlign="start"
class="tb-alarm-comments-user-avatar"
[style.background-color]="displayDataElement.avatarBgColor">
{{ getUserInitials(displayDataElement.displayName) }}
</div>
<div fxFlex fxLayout="column" fxLayoutGap="5px">
<div fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<span class="tb-alarm-comments-user-name">{{ displayDataElement.displayName }}</span>
<span class="tb-alarm-comments-time" *ngIf="displayDataElement.isEdited">
edited {{ displayDataElement.editedDateAgo }}
</span>
<span class="tb-alarm-comments-time" *ngIf="!displayDataElement.isEdited">
{{ displayDataElement.createdDateAgo }}
</span>
</div>
<span class="tb-alarm-comments-text">{{ displayDataElement.commentText }}</span>
</div>
<div fxLayout="row" class="tb-alarm-comments-action-buttons"
[ngClass]="{ 'show-buttons': displayDataElement.showActions }">
<button mat-icon-button
type="button"
(click)="editComment(displayDataElement.commentId)">
<mat-icon class="material-icons">edit</mat-icon>
</button>
<button mat-icon-button
type="button"
(click)="deleteComment(displayDataElement.commentId)">
<mat-icon class="material-icons">delete</mat-icon>
</button>
</div>
</div> </div>
<ng-template #commentEditing> <ng-template #userComment>
<div fxLayoutAlign="row center" fxLayoutGap="8px"> <div class="user-comment" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"
<div fxLayout="row" fxLayoutAlign="center center" *ngIf="!displayDataElement.edit; else commentEditing"
class="tb-alarm-comments-user-avatar" (mouseenter)="onCommentMouseEnter(displayDataElement.commentId, i)"
(mouseleave)="onCommentMouseLeave(i)">
<div class="user-avatar" fxLayout="row" fxLayoutAlign="center center" fxFlexAlign="start" fxHide.xs
[style.background-color]="displayDataElement.avatarBgColor"> [style.background-color]="displayDataElement.avatarBgColor">
{{ getUserInitials(displayDataElement.displayName) }} {{ getUserInitials(displayDataElement.displayName) }}
</div> </div>
<mat-form-field fxFlex appearance="fill" class="mat-block"> <div fxFlex fxLayout="column" fxLayoutGap="5px">
<textarea matInput <div fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
type="text" <span class="user-name">{{ displayDataElement.displayName }}</span>
placeholder="{{ 'alarm-comment.add' | translate }}" <span class="time"
cdkTextareaAutosize [matTooltip]="displayDataElement.createdTime"
cdkAutosizeMinRows="1" matTooltipPosition="right">
cols="1" {{ displayDataElement.createdDateAgo }}
formControlName="alarmCommentEdit" </span>
(keyup.enter)="saveEditedComment(displayDataElement.commentId)" <span class="time" *ngIf="displayDataElement.isEdited"
(keydown.enter)="$event.preventDefault()"> matTooltip="{{ displayDataElement.editedDateAgo }} {{ displayDataElement.editedTime }}"
</textarea> matTooltipPosition="right">
<div matSuffix fxLayout="row"> Edited
<button mat-icon-button </span>
(click)="cancelEdit(displayDataElement.commentId)"
type="button">
<mat-icon class="material-icons red-button">close</mat-icon>
</button>
<button mat-icon-button
type="button"
(click)="saveEditedComment(displayDataElement.commentId)">
<mat-icon class="material-icons green-button">check</mat-icon>
</button>
</div> </div>
</mat-form-field> <span class="text">{{ displayDataElement.commentText }}</span>
</div>
<div fxLayout="row" fxLayout.xs="column" class="action-buttons"
[ngClass]="{ 'show-buttons': displayDataElement.showActions }">
<button mat-icon-button
type="button"
(click)="editComment(displayDataElement.commentId)">
<mat-icon class="material-icons">edit</mat-icon>
</button>
<button mat-icon-button
type="button"
(click)="deleteComment(displayDataElement.commentId)">
<mat-icon class="material-icons">delete</mat-icon>
</button>
</div>
</div> </div>
<ng-template #commentEditing>
<div fxLayoutAlign="row center" fxLayoutGap="8px">
<div fxLayout="row" fxLayoutAlign="center center"
class="user-avatar"
[style.background-color]="displayDataElement.avatarBgColor">
{{ getUserInitials(displayDataElement.displayName) }}
</div>
<mat-form-field fxFlex class="mat-block tb-appearance-transparent">
<textarea matInput
type="text"
placeholder="{{ 'alarm-activity.add' | translate }}"
cdkTextareaAutosize
cdkAutosizeMinRows="1"
cols="1"
formControlName="alarmCommentEdit"
(keyup.enter)="saveEditedComment(displayDataElement.commentId)"
(keydown.enter)="$event.preventDefault()">
</textarea>
<div matSuffix fxLayout="row">
<button mat-icon-button
(click)="cancelEdit(displayDataElement.commentId)"
type="button">
<mat-icon class="material-icons red-button">close</mat-icon>
</button>
<button mat-icon-button
type="button"
(click)="saveEditedComment(displayDataElement.commentId)">
<mat-icon class="material-icons green-button">check</mat-icon>
</button>
</div>
</mat-form-field>
</div>
</ng-template>
</ng-template> </ng-template>
</ng-template> </div>
</div> </div>
<ng-container *ngIf="isDirectionAscending()"> <ng-container *ngIf="isDirectionAscending()">
<ng-container *ngTemplateOutlet="commentInput"></ng-container> <ng-container *ngTemplateOutlet="commentInput"></ng-container>
</ng-container> </ng-container>
</div> </div>
<ng-template #commentInput> <ng-template #commentInput>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" fxFlex> <div style="background-color: white" class="comment-input"
<div fxLayout="row" fxLayoutAlign="center center" [ngClass]="{'newest-first': !isDirectionAscending(), 'oldest-first': isDirectionAscending(), 'activity-only': alarmActivityOnly}">
class="tb-alarm-comments-user-avatar" <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" class="inner-wrap">
*ngIf="userDisplayName$ | async; let userDisplayName" <div fxLayout="row" fxLayoutAlign="center center"
[style.background-color]="getCurrentUserBgColor(userDisplayName)"> class="user-avatar"
{{ getUserInitials(userDisplayName) }} *ngIf="userDisplayName$ | async; let userDisplayName"
</div> [style.background-color]="getCurrentUserBgColor(userDisplayName)">
<mat-form-field appearance="fill" fxFlex class="mat-block"> {{ getUserInitials(userDisplayName) }}
</div>
<mat-form-field fxFlex class="mat-block tb-appearance-transparent">
<textarea matInput <textarea matInput
type="text" type="text"
placeholder="{{ 'alarm-comment.add' | translate }}" placeholder="{{ 'alarm-activity.add' | translate }}"
cdkTextareaAutosize cdkTextareaAutosize
cdkAutosizeMinRows="1" cdkAutosizeMinRows="1"
cols="1" cols="1"
@ -147,16 +165,17 @@
(keyup.enter)="saveComment()" (keyup.enter)="saveComment()"
(keydown.enter)="$event.preventDefault()"> (keydown.enter)="$event.preventDefault()">
</textarea> </textarea>
<button mat-icon-button <button mat-icon-button
type="button" type="button"
matSuffix matSuffix
*ngIf="getAlarmCommentFormControl().value" *ngIf="getAlarmCommentFormControl().value"
(click)="saveComment()"> (click)="saveComment()">
<mat-icon color="primary"> <mat-icon color="primary">
send send
</mat-icon> </mat-icon>
</button> </button>
</mat-form-field> </mat-form-field>
</div>
</div> </div>
</ng-template> </ng-template>
</div> </div>

157
ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.scss

@ -13,69 +13,182 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@use '@angular/material' as mat;
@import '../theme.scss';
$primary-color: rgba(mat.get-color-from-palette($tb-primary, 50), 0.4);
$border: 1px solid mat.get-color-from-palette($tb-primary);
:host { :host {
.tb-alarm-comments { .tb-alarm-comments {
padding: 16px 24px 24px 24px; background-color: $primary-color;
background-color: #fafafa;
max-width: 600px; max-width: 600px;
width: 100%;
&-header { .comment-input {
background-color: #fafafa;
position: sticky; position: sticky;
top: -25px;
z-index: 1; z-index: 1;
margin-bottom: 10px;
&-title { .inner-wrap {
color: rgba(0, 0, 0, 0.76); border: $border;
letter-spacing: 0.25px; padding: 0 24px;
font-weight: 500; background-color: $primary-color;
} }
.mat-icon { &.oldest-first {
color: rgba(0, 0, 0, 0.38); bottom: -24px;
box-shadow: 0px -4px 12px rgba(0, 0, 0, 0.04);
.inner-wrap {
border-radius: 0 0 8px 8px;
}
&.activity-only {
bottom: -1px;
.inner-wrap {
border: none
}
}
}
&.newest-first {
top: 24px;
box-shadow: 0 8px 10px rgba(23, 33, 90, 0.08);
.inner-wrap {
border-top: none;
}
&.activity-only {
top: 48px;
box-shadow: 0 8px 10px rgba(23, 33, 90, 0.08);
.inner-wrap {
border: none;
}
}
}
}
.header {
z-index: 1;
position: sticky;
top: -24px;
background-color: white;
&.activity-only {
top: 0;
}
&-container {
padding: 0 24px;
background-color: $primary-color;
border: $border;
border-bottom: none;
border-radius: 8px 8px 0px 0px;
&.activity-only {
border: none;
}
&.asc {
border-bottom: $border;
box-shadow: 0px 4px 10px rgba(23, 33, 90, 0.08);
&.activity-only {
border: none;
}
}
.header-title {
color: rgba(0, 0, 0, 0.76);
letter-spacing: 0.25px;
font-weight: 500;
}
.mat-icon {
color: rgba(0, 0, 0, 0.38);
}
}
}
.comments-container {
border: $border;
border-top: none;
border-radius: 0px 0px 8px 8px;
&.activity-only {
border: none;
}
&.asc {
border-bottom: none;
border-radius: unset;
}
}
.user-comment {
padding: 4px;
border-radius: 8px;
&:hover {
background-color: $primary-color;
} }
} }
&-user-avatar { .user-avatar {
width: 28px; width: 28px;
min-width: 28px; min-width: 28px;
height: 28px; height: 28px;
min-height: 28px; min-height: 28px;
border-radius: 50%; border-radius: 50%;
font-weight: 700; font-weight: 700;
color: #FFFFFF; color: white;
font-size: 13px; font-size: 13px;
} }
&-user-name { .user-name {
font-size: 16px; font-size: 16px;
color: rgba(0, 0, 0, 0.76); color: rgba(0, 0, 0, 0.76);
font-weight: 500; font-weight: 500;
letter-spacing: 0.25px; letter-spacing: 0.25px;
} }
&-time { .time {
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: rgba(0, 0, 0, 0.38); color: rgba(0, 0, 0, 0.38);
letter-spacing: 0.2px letter-spacing: 0.2px;
border-radius: 16px;
padding: 0 3px;
&:hover {
background: rgba(0, 0, 0, 0.04);
}
} }
&-system-text { .system-comment {
color: rgba(0, 0, 0, 0.38); margin-left: 38px;
@media #{$mat-xs} {
margin-left: 0;
}
}
.system-text {
font-weight: 500; font-weight: 500;
font-size: 14px;
letter-spacing: 0.25px; letter-spacing: 0.25px;
color: rgba(0, 0, 0, 0.38);
} }
&-text { .text {
white-space: pre-line; white-space: pre-line;
word-break: break-word; word-break: break-word;
color: rgba(0, 0, 0, 0.54); font-size: 16px;
letter-spacing: 0.15px; letter-spacing: 0.15px;
color: rgba(0, 0, 0, 0.54);
} }
&-action-buttons { .action-buttons {
visibility: hidden; visibility: hidden;
.mat-icon { .mat-icon {
color: rgba(0, 0, 0, 0.38); color: rgba(0, 0, 0, 0.38);

50
ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.ts

@ -30,13 +30,17 @@ import { map } from 'rxjs/operators';
import { AlarmComment, AlarmCommentInfo, AlarmCommentType } from '@shared/models/alarm.models'; import { AlarmComment, AlarmCommentInfo, AlarmCommentType } from '@shared/models/alarm.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { DatePipe } from '@angular/common';
import { ImportExportService } from '@home/components/import-export/import-export.service';
interface AlarmCommentsDisplayData { interface AlarmCommentsDisplayData {
commentId?: string, commentId?: string,
displayName?: string, displayName?: string,
createdTime: string,
createdDateAgo?: string, createdDateAgo?: string,
edit?: boolean, edit?: boolean,
isEdited?: boolean, isEdited?: boolean,
editedTime?: string;
editedDateAgo?: string, editedDateAgo?: string,
showActions?: boolean, showActions?: boolean,
commentText?: string, commentText?: string,
@ -54,7 +58,7 @@ export class AlarmCommentComponent implements OnInit {
alarmId: string; alarmId: string;
@Input() @Input()
commentsHeaderEnabled: boolean = true; alarmActivityOnly: boolean = false;
authUser: AuthUser; authUser: AuthUser;
@ -85,7 +89,9 @@ export class AlarmCommentComponent implements OnInit {
public fb: FormBuilder, public fb: FormBuilder,
private dialogService: DialogService, private dialogService: DialogService,
public dateAgoPipe: DateAgoPipe, public dateAgoPipe: DateAgoPipe,
private utilsService: UtilsService) { private utilsService: UtilsService,
private datePipe: DatePipe,
private importExportService: ImportExportService) {
this.authUser = getCurrentAuthUser(store); this.authUser = getCurrentAuthUser(store);
@ -110,7 +116,8 @@ export class AlarmCommentComponent implements OnInit {
this.alarmComments = pagedData.data; this.alarmComments = pagedData.data;
this.displayData.length = 0; this.displayData.length = 0;
for (let alarmComment of pagedData.data) { for (let alarmComment of pagedData.data) {
let displayDataElement: AlarmCommentsDisplayData = {}; let displayDataElement = {} as AlarmCommentsDisplayData;
displayDataElement.createdTime = this.datePipe.transform(alarmComment.createdTime, 'yyyy-MM-dd HH:mm:ss');
displayDataElement.createdDateAgo = this.dateAgoPipe.transform(alarmComment.createdTime); displayDataElement.createdDateAgo = this.dateAgoPipe.transform(alarmComment.createdTime);
displayDataElement.commentText = alarmComment.comment.text; displayDataElement.commentText = alarmComment.comment.text;
displayDataElement.isSystemComment = alarmComment.type === AlarmCommentType.SYSTEM; displayDataElement.isSystemComment = alarmComment.type === AlarmCommentType.SYSTEM;
@ -119,7 +126,8 @@ export class AlarmCommentComponent implements OnInit {
displayDataElement.displayName = this.getUserDisplayName(alarmComment); displayDataElement.displayName = this.getUserDisplayName(alarmComment);
displayDataElement.edit = false; displayDataElement.edit = false;
displayDataElement.isEdited = alarmComment.comment.edited; displayDataElement.isEdited = alarmComment.comment.edited;
displayDataElement.editedDateAgo = this.dateAgoPipe.transform(alarmComment.comment.editedOn).toLowerCase(); displayDataElement.editedTime = this.datePipe.transform(alarmComment.comment.editedOn, 'yyyy-MM-dd HH:mm:ss');
displayDataElement.editedDateAgo = this.dateAgoPipe.transform(alarmComment.comment.editedOn) + '\n';
displayDataElement.showActions = false; displayDataElement.showActions = false;
displayDataElement.isSystemComment = false; displayDataElement.isSystemComment = false;
displayDataElement.avatarBgColor = this.utilsService.stringToHslColor(displayDataElement.displayName, displayDataElement.avatarBgColor = this.utilsService.stringToHslColor(displayDataElement.displayName,
@ -137,6 +145,11 @@ export class AlarmCommentComponent implements OnInit {
this.loadAlarmComments(); this.loadAlarmComments();
} }
exportAlarmActivity() {
let fileName = this.translate.instant('alarm.alarm') + '_' + this.translate.instant('alarm-activity.activity');
this.importExportService.exportCsv(this.getDataForExport(), fileName.toLowerCase());
}
saveComment(): void { saveComment(): void {
const commentInputValue: string = this.getAlarmCommentFormControl().value; const commentInputValue: string = this.getAlarmCommentFormControl().value;
if (commentInputValue) { if (commentInputValue) {
@ -194,7 +207,7 @@ export class AlarmCommentComponent implements OnInit {
const alarmCommentInfo: AlarmComment = this.getAlarmCommentById(commentId); const alarmCommentInfo: AlarmComment = this.getAlarmCommentById(commentId);
const commentText: string = alarmCommentInfo.comment.text; const commentText: string = alarmCommentInfo.comment.text;
this.dialogService.confirm( this.dialogService.confirm(
this.translate.instant('alarm-comment.delete-alarm-comment'), this.translate.instant('alarm-activity.delete-alarm-comment'),
commentText, commentText,
this.translate.instant('action.cancel'), this.translate.instant('action.cancel'),
this.translate.instant('action.delete')).subscribe( this.translate.instant('action.delete')).subscribe(
@ -211,15 +224,17 @@ export class AlarmCommentComponent implements OnInit {
} }
getSortDirectionIcon() { getSortDirectionIcon() {
return this.alarmCommentSortOrder.direction === Direction.DESC ? 'arrow_downward' : 'arrow_upward' return this.alarmCommentSortOrder.direction === Direction.DESC ? 'mdi:sort-descending' : 'mdi:sort-ascending'
} }
isDirectionAscending() { getSortDirectionTooltipText() {
return this.alarmCommentSortOrder.direction === Direction.ASC; let text = this.alarmCommentSortOrder.direction === Direction.DESC ? 'alarm-activity.newest-first' :
'alarm-activity.oldest-first';
return this.translate.instant(text);
} }
isDirectionDescending() { isDirectionAscending() {
return this.alarmCommentSortOrder.direction === Direction.DESC; return this.alarmCommentSortOrder.direction === Direction.ASC;
} }
onCommentMouseEnter(commentId: string, displayDataIndex: number): void { onCommentMouseEnter(commentId: string, displayDataIndex: number): void {
@ -292,4 +307,19 @@ export class AlarmCommentComponent implements OnInit {
return this.displayData.find(commentDisplayData => commentDisplayData.commentId === commentId); return this.displayData.find(commentDisplayData => commentDisplayData.commentId === commentId);
} }
private getDataForExport() {
let dataToExport = [];
for (let row of this.displayData) {
let exportRow = {
[this.translate.instant('alarm-activity.author')]: row.isSystemComment ?
this.translate.instant('alarm-activity.system') : row.displayName,
[this.translate.instant('alarm-activity.created-date')]: row.createdTime,
[this.translate.instant('alarm-activity.edited-date')]: row.editedTime,
[this.translate.instant('alarm-activity.text')]: row.commentText
}
dataToExport.push(exportRow)
}
return dataToExport;
}
} }

72
ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.html

@ -28,90 +28,64 @@
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar> </mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content style="padding: 24px 0 0 0"> <div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async" style="padding: 0 24px"> <fieldset [disabled]="isLoading$ | async" style="margin-bottom: 22px">
<div fxLayout="row" fxLayoutGap="6px"> <div fxLayout="row" fxLayoutGap="6px">
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>alarm.originator</mat-label> <mat-label translate>alarm.originator</mat-label>
<input matInput formControlName="originatorName" readonly> <input matInput formControlName="originatorName" readonly>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>alarm.created-time</mat-label> <mat-label translate>alarm.severity</mat-label>
<input matInput formControlName="createdTime" readonly> <input matInput formControlName="alarmSeverity" readonly
[ngStyle]="{fontWeight: 'bold', color: alarmSeverityColorsMap.get((alarm$ | async)?.severity)}">
</mat-form-field> </mat-form-field>
</div> </div>
<div fxLayout="row" fxLayoutGap="6px"> <div fxLayout="row" fxLayoutGap="6px">
<mat-form-field fxFlex class="mat-block"> <mat-form-field *ngIf="alarmFormGroup.get('startTime').value" fxFlex class="mat-block">
<mat-label translate>alarm.type</mat-label> <mat-label translate>alarm.start-time</mat-label>
<input matInput formControlName="type" readonly> <input matInput formControlName="startTime" readonly>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> <mat-form-field *ngIf="alarmFormGroup.get('duration').value" fxFlex class="mat-block">
<mat-label translate>alarm.severity</mat-label> <mat-label translate>alarm.duration</mat-label>
<input matInput formControlName="alarmSeverity" readonly <input matInput formControlName="duration" readonly>
[ngStyle]="{fontWeight: 'bold', color: alarmSeverityColorsMap.get((alarm$ | async)?.severity)}">
</mat-form-field> </mat-form-field>
</div> </div>
<div fxLayout="row" fxLayoutGap="6px"> <div fxLayout="row" fxLayoutGap="6px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>alarm.type</mat-label>
<input matInput formControlName="type" readonly>
</mat-form-field>
<mat-form-field fxFlex class="mat-block"> <mat-form-field fxFlex class="mat-block">
<mat-label translate>alarm.status</mat-label> <mat-label translate>alarm.status</mat-label>
<input matInput formControlName="alarmStatus" readonly> <input matInput formControlName="alarmStatus" readonly>
</mat-form-field> </mat-form-field>
<tb-alarm-assignee fxFlex style="padding-top: 9px"
[alarm]="alarm$ | async"
(alarmReassigned)="onReassign()">
</tb-alarm-assignee>
</div> </div>
<mat-expansion-panel class="tb-alarm-details"> <mat-expansion-panel class="tb-alarm-details">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap" style="margin-bottom: 8px">
<mat-panel-title> <mat-panel-title>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxLayoutAlign="end center" translate>
alarm.advanced-info alarm.show-more
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<div fxLayout="row" fxLayoutGap="6px" *ngIf="alarmFormGroup.get('startTime').value ||
alarmFormGroup.get('endTime').value">
<mat-form-field *ngIf="alarmFormGroup.get('startTime').value" fxFlex class="mat-block">
<mat-label translate>alarm.start-time</mat-label>
<input matInput formControlName="startTime" readonly>
</mat-form-field>
<mat-form-field *ngIf="alarmFormGroup.get('endTime').value" fxFlex class="mat-block">
<mat-label translate>alarm.end-time</mat-label>
<input matInput formControlName="endTime" readonly>
</mat-form-field>
<span fxFlex *ngIf="!alarmFormGroup.get('startTime').value || !alarmFormGroup.get('endTime').value"></span>
</div>
<div fxLayout="row" fxLayoutGap="6px" *ngIf="alarmFormGroup.get('ackTime').value ||
alarmFormGroup.get('clearTime').value">
<mat-form-field *ngIf="alarmFormGroup.get('ackTime').value" fxFlex class="mat-block">
<mat-label translate>alarm.ack-time</mat-label>
<input matInput formControlName="ackTime" readonly>
</mat-form-field>
<mat-form-field *ngIf="alarmFormGroup.get('clearTime').value" fxFlex class="mat-block">
<mat-label translate>alarm.clear-time</mat-label>
<input matInput formControlName="clearTime" readonly>
</mat-form-field>
<span fxFlex *ngIf="!alarmFormGroup.get('ackTime').value || !alarmFormGroup.get('clearTime').value"></span>
</div>
<tb-json-object-edit <tb-json-object-edit
*ngIf="displayDetails" *ngIf="displayDetails"
formControlName="alarmDetails" formControlName="alarmDetails"
readonly readonly
label="{{ 'alarm.details' | translate }}"> label="{{ 'alarm.additional-info' | translate }}">
</tb-json-object-edit> </tb-json-object-edit>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </fieldset>
<tb-alarm-assignee fxFlex [allowAssign]="allowAssign"
[alarm]="alarm$ | async"
(alarmReassigned)="onReassign()">
</tb-alarm-assignee>
<tb-alarm-comment #alarmCommentComponent [alarmId]="alarmId"></tb-alarm-comment> <tb-alarm-comment #alarmCommentComponent [alarmId]="alarmId"></tb-alarm-comment>
</div> </div>
<div mat-dialog-actions fxLayout="row"> <div mat-dialog-actions fxLayout="row">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="close()" cdkFocusInitial>
{{ 'action.close' | translate }}
</button>
<span fxFlex></span> <span fxFlex></span>
<div fxLayout="row" *ngIf="alarm$ | async; let alarm;" fxLayoutGap="8px"> <div fxLayout="row" *ngIf="alarm$ | async; let alarm;" fxLayoutGap="8px">
<button *ngIf="allowAcknowledgment && (alarm.status === alarmStatuses.ACTIVE_UNACK || <button *ngIf="allowAcknowledgment && (alarm.status === alarmStatuses.ACTIVE_UNACK ||

1
ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.scss

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
:host ::ng-deep { :host ::ng-deep {
.assignee-field { .assignee-field {
.mat-form-field-label-wrapper { .mat-form-field-label-wrapper {

40
ui-ngx/src/app/modules/home/components/alarm/alarm-details-dialog.component.ts

@ -34,6 +34,7 @@ import { tap } from 'rxjs/operators';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { AlarmCommentComponent } from '@home/components/alarm/alarm-comment.component'; import { AlarmCommentComponent } from '@home/components/alarm/alarm-comment.component';
import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe';
export interface AlarmDetailsDialogData { export interface AlarmDetailsDialogData {
alarmId?: string; alarmId?: string;
@ -41,6 +42,7 @@ export interface AlarmDetailsDialogData {
allowAcknowledgment: boolean; allowAcknowledgment: boolean;
allowClear: boolean; allowClear: boolean;
displayDetails: boolean; displayDetails: boolean;
allowAssign: boolean;
} }
@Component({ @Component({
@ -56,6 +58,7 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia
allowAcknowledgment: boolean; allowAcknowledgment: boolean;
allowClear: boolean; allowClear: boolean;
displayDetails: boolean; displayDetails: boolean;
allowAssign: boolean;
loadAlarmSubject = new ReplaySubject<AlarmInfo>(); loadAlarmSubject = new ReplaySubject<AlarmInfo>();
alarm$: Observable<AlarmInfo> = this.loadAlarmSubject.asObservable().pipe( alarm$: Observable<AlarmInfo> = this.loadAlarmSubject.asObservable().pipe(
@ -72,6 +75,7 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
private datePipe: DatePipe, private datePipe: DatePipe,
private millisecondsToTimeStringPipe: MillisecondsToTimeStringPipe,
private translate: TranslateService, private translate: TranslateService,
@Inject(MAT_DIALOG_DATA) public data: AlarmDetailsDialogData, @Inject(MAT_DIALOG_DATA) public data: AlarmDetailsDialogData,
private alarmService: AlarmService, private alarmService: AlarmService,
@ -82,17 +86,15 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia
this.allowAcknowledgment = data.allowAcknowledgment; this.allowAcknowledgment = data.allowAcknowledgment;
this.allowClear = data.allowClear; this.allowClear = data.allowClear;
this.displayDetails = data.displayDetails; this.displayDetails = data.displayDetails;
this.allowAssign = data.allowAssign;
this.alarmFormGroup = this.fb.group( this.alarmFormGroup = this.fb.group(
{ {
createdTime: [''],
originatorName: [''], originatorName: [''],
alarmSeverity: [''],
startTime: [''], startTime: [''],
endTime: [''], duration: [''],
ackTime: [''],
clearTime: [''],
type: [''], type: [''],
alarmSeverity: [''],
alarmStatus: [''], alarmStatus: [''],
alarmDetails: [null] alarmDetails: [null]
} }
@ -116,29 +118,25 @@ export class AlarmDetailsDialogComponent extends DialogComponent<AlarmDetailsDia
} }
loadAlarmFields(alarm: AlarmInfo) { loadAlarmFields(alarm: AlarmInfo) {
this.alarmFormGroup.get('createdTime')
.patchValue(this.datePipe.transform(alarm.createdTime, 'yyyy-MM-dd HH:mm:ss'));
this.alarmFormGroup.get('originatorName') this.alarmFormGroup.get('originatorName')
.patchValue(alarm.originatorName); .patchValue(alarm.originatorLabel ? alarm.originatorLabel : alarm.originatorName);
this.alarmFormGroup.get('alarmSeverity')
.patchValue(this.translate.instant(alarmSeverityTranslations.get(alarm.severity)));
if (alarm.startTs) { if (alarm.startTs) {
this.alarmFormGroup.get('startTime') this.alarmFormGroup.get('startTime')
.patchValue(this.datePipe.transform(alarm.startTs, 'yyyy-MM-dd HH:mm:ss')); .patchValue(this.datePipe.transform(alarm.startTs, 'yyyy-MM-dd HH:mm:ss'));
} }
if (alarm.endTs) { if (alarm.startTs || alarm.endTs) {
this.alarmFormGroup.get('endTime') let duration = '';
.patchValue(this.datePipe.transform(alarm.endTs, 'yyyy-MM-dd HH:mm:ss')); if (alarm.startTs && (alarm.status === AlarmStatus.ACTIVE_ACK || alarm.status === AlarmStatus.ACTIVE_UNACK)) {
} duration = this.millisecondsToTimeStringPipe.transform(Date.now() - alarm.startTs);
if (alarm.ackTs) { }
this.alarmFormGroup.get('ackTime') if (alarm.endTs && (alarm.status === AlarmStatus.CLEARED_ACK || alarm.status === AlarmStatus.CLEARED_UNACK)) {
.patchValue(this.datePipe.transform(alarm.ackTs, 'yyyy-MM-dd HH:mm:ss')); duration = this.millisecondsToTimeStringPipe.transform(alarm.endTs - alarm.startTs);
} }
if (alarm.clearTs) { this.alarmFormGroup.get('duration').patchValue(duration);
this.alarmFormGroup.get('clearTime')
.patchValue(this.datePipe.transform(alarm.clearTs, 'yyyy-MM-dd HH:mm:ss'));
} }
this.alarmFormGroup.get('type').patchValue(alarm.type); this.alarmFormGroup.get('type').patchValue(alarm.type);
this.alarmFormGroup.get('alarmSeverity')
.patchValue(this.translate.instant(alarmSeverityTranslations.get(alarm.severity)));
this.alarmFormGroup.get('alarmStatus') this.alarmFormGroup.get('alarmStatus')
.patchValue(this.translate.instant(alarmStatusTranslations.get(alarm.status))); .patchValue(this.translate.instant(alarmStatusTranslations.get(alarm.status)));
this.alarmFormGroup.get('alarmDetails').patchValue(alarm.details); this.alarmFormGroup.get('alarmDetails').patchValue(alarm.details);

17
ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts

@ -53,7 +53,8 @@ import { Authority } from '@shared/models/authority.enum';
import { ChangeDetectorRef, Injector, StaticProvider, ViewContainerRef } from '@angular/core'; import { ChangeDetectorRef, Injector, StaticProvider, ViewContainerRef } from '@angular/core';
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'; import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { import {
ALARM_ASSIGNEE_PANEL_DATA, AlarmAssigneePanelComponent, ALARM_ASSIGNEE_PANEL_DATA,
AlarmAssigneePanelComponent,
AlarmAssigneePanelData AlarmAssigneePanelData
} from '@home/components/alarm/alarm-assignee-panel.component'; } from '@home/components/alarm/alarm-assignee-panel.component';
import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentPortal } from '@angular/cdk/portal';
@ -168,7 +169,7 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
} }
showAlarmDetails(entity: AlarmInfo) { showAlarmDetails(entity: AlarmInfo) {
const isPermissionWrite = this.authUser.authority !== Authority.CUSTOMER_USER || entity.customerId.id === this.authUser.customerId; const isPermissionWrite = this.authUser.authority !== Authority.CUSTOMER_USER || entity.customerId?.id === this.authUser.customerId;
this.dialog.open<AlarmDetailsDialogComponent, AlarmDetailsDialogData, boolean> this.dialog.open<AlarmDetailsDialogComponent, AlarmDetailsDialogData, boolean>
(AlarmDetailsDialogComponent, (AlarmDetailsDialogComponent,
{ {
@ -179,7 +180,8 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
alarm: entity, alarm: entity,
allowAcknowledgment: isPermissionWrite, allowAcknowledgment: isPermissionWrite,
allowClear: isPermissionWrite, allowClear: isPermissionWrite,
displayDetails: true displayDetails: true,
allowAssign: true
} }
}).afterClosed().subscribe( }).afterClosed().subscribe(
(res) => { (res) => {
@ -281,8 +283,13 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
} }
]; ];
const injector = Injector.create({parent: this.viewContainerRef.injector, providers}); const injector = Injector.create({parent: this.viewContainerRef.injector, providers});
overlayRef.attach(new ComponentPortal(AlarmAssigneePanelComponent, const componentRef = overlayRef.attach(new ComponentPortal(AlarmAssigneePanelComponent,
this.viewContainerRef, injector)).onDestroy(() => this.updateData()); this.viewContainerRef, injector));
componentRef.onDestroy(() => {
if (componentRef.instance.reassigned) {
this.updateData()
}
});
} }
} }

66
ui-ngx/src/app/modules/home/components/alarm/alarm-table.component.scss

@ -14,42 +14,44 @@
* limitations under the License. * limitations under the License.
*/ */
:host ::ng-deep { :host ::ng-deep {
tb-entities-table.tb-details-mode { tb-entities-table {
.mat-drawer-container { &.tb-details-mode {
background-color: white; .mat-drawer-container {
.assignee-cell { background-color: white;
display: flex; }
justify-content: flex-start; }
align-items: center; .assignee-cell {
.assigned-container { display: flex;
max-width: 180px; justify-content: flex-start;
overflow: hidden; align-items: center;
white-space: nowrap; .assigned-container {
text-overflow: ellipsis; max-width: 180px;
.user-avatar { overflow: hidden;
display: inline-flex; white-space: nowrap;
justify-content: center; text-overflow: ellipsis;
align-items: center; .user-avatar {
margin-right: 8px; display: inline-flex;
border-radius: 50%; justify-content: center;
width: 28px; align-items: center;
height: 28px; margin-right: 8px;
min-width: 28px; border-radius: 50%;
min-height: 28px;
color: white;
font-size: 13px;
font-weight: 700;
}
}
.material-icons.unassigned-icon {
width: 28px; width: 28px;
height: 28px; height: 28px;
font-size: 28px; min-width: 28px;
margin-right: 8px; min-height: 28px;
color: rgba(0, 0, 0, 0.38); color: white;
overflow: visible; font-size: 13px;
font-weight: 700;
} }
} }
.material-icons.unassigned-icon {
width: 28px;
height: 28px;
font-size: 28px;
margin-right: 8px;
color: rgba(0, 0, 0, 0.38);
overflow: visible;
}
} }
} }
} }

5
ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts

@ -150,6 +150,11 @@ export const ZIP_TYPE: FileType = {
extension: 'zip' extension: 'zip'
}; };
export const CSV_TYPE: FileType = {
mimeType: 'attachament/csv',
extension: 'csv'
};
export function convertCSVToJson(csvdata: string, config: CsvToJsonConfig, export function convertCSVToJson(csvdata: string, config: CsvToJsonConfig,
onError: (messageId: string, params?: any) => void): CsvToJsonResult | number { onError: (messageId: string, params?: any) => void): CsvToJsonResult | number {
config = config || {}; config = config || {};

30
ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts

@ -47,6 +47,7 @@ import { ItemBufferService, WidgetItem } from '@core/services/item-buffer.servic
import { import {
BulkImportRequest, BulkImportRequest,
BulkImportResult, BulkImportResult,
CSV_TYPE,
FileType, FileType,
ImportWidgetResult, ImportWidgetResult,
JSON_TYPE, JSON_TYPE,
@ -597,6 +598,35 @@ export class ImportExportService {
); );
} }
private processCSVCell(cellData: any): any {
if (isString(cellData)) {
let result = cellData.replace(/"/g, '""');
if (result.search(/([",\n])/g) >= 0) {
result = `"${result}"`;
}
return result;
}
return cellData;
}
public exportCsv(data: {[key: string]: any}[], filename: string) {
let colsHead: string;
let colsData: string;
if (data && data.length) {
colsHead = Object.keys(data[0]).map(key => [this.processCSVCell(key)]).join(';');
colsData = data.map(obj => [
Object.keys(obj).map(col => [
this.processCSVCell(obj[col])
]).join(';')
]).join('\n');
} else {
colsHead = '';
colsData = '';
}
const csvData = `${colsHead}\n${colsData}`;
this.downloadFile(csvData, filename, CSV_TYPE);
}
public exportText(data: string | Array<string>, filename: string) { public exportText(data: string | Array<string>, filename: string) {
let content = data; let content = data;
if (Array.isArray(data)) { if (Array.isArray(data)) {

15
ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html

@ -66,6 +66,21 @@
{{ 'device-profile.not-valid-multi-character' | translate}} {{ 'device-profile.not-valid-multi-character' | translate}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>device-profile.attributes-subscribe-topic-filter</mat-label>
<input matInput required
formControlName="deviceAttributesSubscribeTopic"
type="text">
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesSubscribeTopic').hasError('required')">
{{ 'device-profile.attributes-subscribe-topic-filter-required' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesSubscribeTopic').hasError('invalidSingleTopicCharacter')">
{{ 'device-profile.not-valid-single-character' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesSubscribeTopic').hasError('invalidMultiTopicCharacter')">
{{ 'device-profile.not-valid-multi-character' | translate}}
</mat-error>
</mat-form-field>
</div> </div>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.hasError('unique')"> <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.hasError('unique')">
{{ 'device-profile.mqtt-device-topic-filters-unique' | translate }} {{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}

1
ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts

@ -91,6 +91,7 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
ngOnInit() { ngOnInit() {
this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({ this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({
deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
deviceAttributesSubscribeTopic: [null, [Validators.required, this.validationMQTTTopic()]],
deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
sparkplug: [false], sparkplug: [false],
sparkplugAttributesMetricNames: [null], sparkplugAttributesMetricNames: [null],

26
ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts

@ -143,7 +143,7 @@ interface AlarmsTableWidgetSettings extends TableWidgetSettings {
enableSelection: boolean; enableSelection: boolean;
enableStatusFilter?: boolean; enableStatusFilter?: boolean;
enableFilter: boolean; enableFilter: boolean;
displayComments: boolean; displayActivity: boolean;
displayDetails: boolean; displayDetails: boolean;
allowAcknowledgment: boolean; allowAcknowledgment: boolean;
allowClear: boolean; allowClear: boolean;
@ -154,7 +154,7 @@ interface AlarmWidgetActionDescriptor extends TableCellButtonActionDescriptor {
details?: boolean; details?: boolean;
acknowledge?: boolean; acknowledge?: boolean;
clear?: boolean; clear?: boolean;
comments?: boolean; activity?: boolean;
} }
@Component({ @Component({
@ -197,7 +197,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
private alarmsTitlePattern: string; private alarmsTitlePattern: string;
private displayComments = false; private displayActivity = false;
private displayDetails = true; private displayDetails = true;
public allowAcknowledgment = true; public allowAcknowledgment = true;
private allowClear = true; private allowClear = true;
@ -335,7 +335,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
private initializeConfig() { private initializeConfig() {
this.ctx.widgetActions = [this.searchAction, this.alarmFilterAction, this.columnDisplayAction]; this.ctx.widgetActions = [this.searchAction, this.alarmFilterAction, this.columnDisplayAction];
this.displayComments = isDefined(this.settings.displayComments) ? this.settings.displayComments : false; this.displayActivity = isDefined(this.settings.displayActivity) ? this.settings.displayActivity : false;
this.displayDetails = isDefined(this.settings.displayDetails) ? this.settings.displayDetails : true; this.displayDetails = isDefined(this.settings.displayDetails) ? this.settings.displayDetails : true;
this.allowAcknowledgment = isDefined(this.settings.allowAcknowledgment) ? this.settings.allowAcknowledgment : true; this.allowAcknowledgment = isDefined(this.settings.allowAcknowledgment) ? this.settings.allowAcknowledgment : true;
this.allowClear = isDefined(this.settings.allowClear) ? this.settings.allowClear : true; this.allowClear = isDefined(this.settings.allowClear) ? this.settings.allowClear : true;
@ -464,12 +464,12 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
this.sortOrderProperty = sortColumn ? sortColumn.def : null; this.sortOrderProperty = sortColumn ? sortColumn.def : null;
const actionCellDescriptors: AlarmWidgetActionDescriptor[] = []; const actionCellDescriptors: AlarmWidgetActionDescriptor[] = [];
if (this.displayComments) { if (this.displayActivity) {
actionCellDescriptors.push( actionCellDescriptors.push(
{ {
displayName: this.translate.instant('alarm-comment.comments'), displayName: this.translate.instant('alarm-activity.activity'),
icon: 'comment', icon: 'comment',
comments: true activity: true
} as AlarmWidgetActionDescriptor } as AlarmWidgetActionDescriptor
); );
} }
@ -821,8 +821,8 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
this.ackAlarm($event, alarm); this.ackAlarm($event, alarm);
} else if (actionDescriptor.clear) { } else if (actionDescriptor.clear) {
this.clearAlarm($event, alarm); this.clearAlarm($event, alarm);
} else if (actionDescriptor.comments) { } else if (actionDescriptor.activity) {
this.openAlarmComments($event, alarm); this.openAlarmActivity($event, alarm);
} else { } else {
if ($event) { if ($event) {
$event.stopPropagation(); $event.stopPropagation();
@ -864,7 +864,8 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
alarmId: alarm.id.id, alarmId: alarm.id.id,
allowAcknowledgment: this.allowAcknowledgment, allowAcknowledgment: this.allowAcknowledgment,
allowClear: this.allowClear, allowClear: this.allowClear,
displayDetails: true displayDetails: true,
allowAssign: this.allowAssign
} }
}).afterClosed().subscribe( }).afterClosed().subscribe(
(res) => { (res) => {
@ -988,7 +989,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
} }
} }
private openAlarmComments($event: Event, alarm: AlarmDataInfo) { private openAlarmActivity($event: Event, alarm: AlarmDataInfo) {
if ($event) { if ($event) {
$event.stopPropagation(); $event.stopPropagation();
} }
@ -999,8 +1000,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
disableClose: true, disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: { data: {
alarmId: alarm.id.id, alarmId: alarm.id.id
commentsHeaderEnabled: false
} }
}).afterClosed() }).afterClosed()
} }

4
ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html

@ -58,8 +58,8 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<section fxLayout="column" fxLayoutGap="8px"> <section fxLayout="column" fxLayoutGap="8px">
<mat-slide-toggle formControlName="displayComments"> <mat-slide-toggle formControlName="displayActivity">
{{ 'widgets.table.display-alarm-comments' | translate }} {{ 'widgets.table.display-alarm-activity' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle fxFlex formControlName="displayDetails"> <mat-slide-toggle fxFlex formControlName="displayDetails">
{{ 'widgets.table.display-alarm-details' | translate }} {{ 'widgets.table.display-alarm-details' | translate }}

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts

@ -74,7 +74,7 @@ export class AlarmsTableWidgetSettingsComponent extends WidgetSettingsComponent
allowAcknowledgment: [settings.allowAcknowledgment, []], allowAcknowledgment: [settings.allowAcknowledgment, []],
allowClear: [settings.allowClear, []], allowClear: [settings.allowClear, []],
allowAssign: [settings.allowAssign, []], allowAssign: [settings.allowAssign, []],
displayComments: [settings.displayComments, []], displayActivity: [settings.displayActivity, []],
displayPagination: [settings.displayPagination, []], displayPagination: [settings.displayPagination, []],
defaultPageSize: [settings.defaultPageSize, [Validators.min(1)]], defaultPageSize: [settings.defaultPageSize, [Validators.min(1)]],
defaultSortOrder: [settings.defaultSortOrder, []], defaultSortOrder: [settings.defaultSortOrder, []],

2
ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts

@ -321,6 +321,8 @@ export class RuleNotificationDialogComponent extends
if (this.ruleNotification) { if (this.ruleNotification) {
if (this.data.isCopy) { if (this.data.isCopy) {
this.ruleNotification.name += ` (${this.translate.instant('action.copy')})`; this.ruleNotification.name += ` (${this.translate.instant('action.copy')})`;
} else {
this.ruleNotificationForm.get('triggerType').disable({emitEvent: false});
} }
this.ruleNotificationForm.reset({}, {emitEvent: false}); this.ruleNotificationForm.reset({}, {emitEvent: false});
this.ruleNotificationForm.patchValue(this.ruleNotification, {emitEvent: false}); this.ruleNotificationForm.patchValue(this.ruleNotification, {emitEvent: false});

4
ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts

@ -87,7 +87,7 @@ export class TemplateNotificationDialogComponent
if (isDefinedAndNotNull(this.data?.predefinedType)) { if (isDefinedAndNotNull(this.data?.predefinedType)) {
this.hideSelectType = true; this.hideSelectType = true;
this.templateNotificationForm.get('notificationType').setValue(this.data.predefinedType, {emitEvents: false}); this.templateNotificationForm.get('notificationType').setValue(this.data.predefinedType, {emitEvent: false});
} }
if (data.isAdd || data.isCopy) { if (data.isAdd || data.isCopy) {
@ -98,6 +98,8 @@ export class TemplateNotificationDialogComponent
if (this.templateNotification) { if (this.templateNotification) {
if (this.data.isCopy) { if (this.data.isCopy) {
this.templateNotification.name += ` (${this.translate.instant('action.copy')})`; this.templateNotification.name += ` (${this.translate.instant('action.copy')})`;
} else {
this.templateNotificationForm.get('notificationType').disable({emitEvent: false});
} }
this.templateNotificationForm.reset({}, {emitEvent: false}); this.templateNotificationForm.reset({}, {emitEvent: false});
this.templateNotificationForm.patchValue(this.templateNotification, {emitEvent: false}); this.templateNotificationForm.patchValue(this.templateNotification, {emitEvent: false});

8
ui-ngx/src/assets/help/en_US/widget/action/custom_additional_params.md

@ -1,4 +1,4 @@
#### Additional params object #### Additional params object
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
@ -16,10 +16,10 @@ An optional key/value object holding additional entity parameters depending on w
</li> </li>
</ul> </ul>
</li> </li>
<li>Alarms table widget (<i>On row click</i> or <i>Action cell button</i>) - <b>additionalParams:</b> <code>{ alarm: <a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a> }</code>: <li>Alarms table widget (<i>On row click</i> or <i>Action cell button</i>) - <b>additionalParams:</b> <code>{ alarm: <a href="https://github.com/thingsboard/thingsboard/blob/7049f564b4f2a1f49f730c72a1c62f9f24aeb7cc/ui-ngx/src/app/shared/models/alarm.models.ts#L147" target="_blank">AlarmDataInfo</a> }</code>:
<ul> <ul>
<li><b>alarm:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a></code> - An <li><b>alarm:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/7049f564b4f2a1f49f730c72a1c62f9f24aeb7cc/ui-ngx/src/app/shared/models/alarm.models.ts#L147" target="_blank">AlarmDataInfo</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a> object <a href="https://github.com/thingsboard/thingsboard/blob/7049f564b4f2a1f49f730c72a1c62f9f24aeb7cc/ui-ngx/src/app/shared/models/alarm.models.ts#L147" target="_blank">AlarmDataInfo</a> object
presenting basic alarm properties (ex. <code>type</code>, <code>severity</code>, <code>originator</code>, etc.) and <br> provides access to other alarm or originator entity fields/attributes/timeseries declared in widget datasource configuration. presenting basic alarm properties (ex. <code>type</code>, <code>severity</code>, <code>originator</code>, etc.) and <br> provides access to other alarm or originator entity fields/attributes/timeseries declared in widget datasource configuration.
</li> </li>
</ul> </ul>

6
ui-ngx/src/assets/locale/locale.constant-cs_CZ.json

@ -1104,8 +1104,10 @@
"support-level-wildcards": "Jsou podporovány jednoúrovňové <code>[+]</code> a víceúrovňové <code>[#]</code> zástupné znaky.", "support-level-wildcards": "Jsou podporovány jednoúrovňové <code>[+]</code> a víceúrovňové <code>[#]</code> zástupné znaky.",
"telemetry-topic-filter": "Filtr fronty telemetrie", "telemetry-topic-filter": "Filtr fronty telemetrie",
"telemetry-topic-filter-required": "Filtr fronty telemetrie je povinný.", "telemetry-topic-filter-required": "Filtr fronty telemetrie je povinný.",
"attributes-topic-filter": "Filtr atributů fronty", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Filtr atributů fronty je povinný.", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Proto schéma telemetrie", "telemetry-proto-schema": "Proto schéma telemetrie",
"telemetry-proto-schema-required": "Proto schéma telemetrie je povinné.", "telemetry-proto-schema-required": "Proto schéma telemetrie je povinné.",
"attributes-proto-schema": "Atributy proto schémata", "attributes-proto-schema": "Atributy proto schémata",

24
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -466,6 +466,7 @@
"end-time": "End time", "end-time": "End time",
"ack-time": "Acknowledged time", "ack-time": "Acknowledged time",
"clear-time": "Cleared time", "clear-time": "Cleared time",
"duration": "Duration",
"alarm-severity-list": "Alarm severity list", "alarm-severity-list": "Alarm severity list",
"any-severity": "Any severity", "any-severity": "Any severity",
"severity-critical": "Critical", "severity-critical": "Critical",
@ -501,15 +502,24 @@
"any-type": "Any type", "any-type": "Any type",
"search-propagated-alarms": "Search propagated alarms", "search-propagated-alarms": "Search propagated alarms",
"comments": "Alarm comments", "comments": "Alarm comments",
"advanced-info": "Advanced info" "show-more": "Show more",
"additional-info": "Additional info"
}, },
"alarm-comment": { "alarm-activity": {
"add": "Add a comment...", "add": "Add a comment...",
"alarm-comment": "Alarm comment", "alarm-comment": "Alarm comment",
"comments": "Comments", "comments": "Comments",
"delete-alarm-comment": "Do you want to delete this comment?", "delete-alarm-comment": "Do you want to delete this comment?",
"refresh": "Refresh", "refresh": "Refresh",
"sort-direction": "Sort direction" "oldest-first": "Oldest first",
"newest-first": "Newest first",
"activity": "Activity",
"export": "Export to CSV",
"author": "Author",
"created-date": "Created date",
"edited-date": "Edited date",
"text": "Text",
"system": "System"
}, },
"alias": { "alias": {
"add": "Add alias", "add": "Add alias",
@ -1430,8 +1440,10 @@
"support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.", "support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.",
"telemetry-topic-filter": "Telemetry topic filter", "telemetry-topic-filter": "Telemetry topic filter",
"telemetry-topic-filter-required": "Telemetry topic filter is required.", "telemetry-topic-filter-required": "Telemetry topic filter is required.",
"attributes-topic-filter": "Attributes topic filter", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Attributes topic filter is required.", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Telemetry proto schema", "telemetry-proto-schema": "Telemetry proto schema",
"telemetry-proto-schema-required": "Telemetry proto schema is required.", "telemetry-proto-schema-required": "Telemetry proto schema is required.",
"attributes-proto-schema": "Attributes proto schema", "attributes-proto-schema": "Attributes proto schema",
@ -5045,7 +5057,7 @@
"display-alarm-details": "Display alarm details", "display-alarm-details": "Display alarm details",
"allow-alarms-ack": "Allow alarms acknowledgment", "allow-alarms-ack": "Allow alarms acknowledgment",
"allow-alarms-clear": "Allow alarms clear", "allow-alarms-clear": "Allow alarms clear",
"display-alarm-comments": "Display alarm comments", "display-alarm-activity": "Display alarm activity",
"allow-alarms-assign": "Allow alarms assignment" "allow-alarms-assign": "Allow alarms assignment"
}, },
"value-source": { "value-source": {

6
ui-ngx/src/assets/locale/locale.constant-es_ES.json

@ -1298,8 +1298,10 @@
"support-level-wildcards": "Se soportan los wilcards únicos <code>[+]</code> y multi-nivel <code>[#]</code>.", "support-level-wildcards": "Se soportan los wilcards únicos <code>[+]</code> y multi-nivel <code>[#]</code>.",
"telemetry-topic-filter": "Filtro de topic en telemetría", "telemetry-topic-filter": "Filtro de topic en telemetría",
"telemetry-topic-filter-required": "Se requiere filtro de topic (telemetría).", "telemetry-topic-filter-required": "Se requiere filtro de topic (telemetría).",
"attributes-topic-filter": "Filtro de topic en atributos", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Se requiere filtro de topic (atributos).", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Proto esquema de telemetría", "telemetry-proto-schema": "Proto esquema de telemetría",
"telemetry-proto-schema-required": "Se requiere proto esquema de telemetría.", "telemetry-proto-schema-required": "Se requiere proto esquema de telemetría.",
"attributes-proto-schema": "Proto esquema de atributos", "attributes-proto-schema": "Proto esquema de atributos",

6
ui-ngx/src/assets/locale/locale.constant-fr_FR.json

@ -1129,8 +1129,10 @@
"support-level-wildcards": "<code>[+]</code> unique et wildcards de <code>[#]</code> multi-niveaux supportés.", "support-level-wildcards": "<code>[+]</code> unique et wildcards de <code>[#]</code> multi-niveaux supportés.",
"telemetry-topic-filter": "Filtre de sujets de télémétrie", "telemetry-topic-filter": "Filtre de sujets de télémétrie",
"telemetry-topic-filter-required": "Filtre de sujets de télémétrie est requis.", "telemetry-topic-filter-required": "Filtre de sujets de télémétrie est requis.",
"attributes-topic-filter": "Filtre de sujets d'attributs", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Filtre de sujets d'attributs est requis.", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Schéma proto de télémétrie", "telemetry-proto-schema": "Schéma proto de télémétrie",
"telemetry-proto-schema-required": "Schéma proto de télémétrie est requis.", "telemetry-proto-schema-required": "Schéma proto de télémétrie est requis.",
"attributes-proto-schema": "Schéma proto d'attributs", "attributes-proto-schema": "Schéma proto d'attributs",

6
ui-ngx/src/assets/locale/locale.constant-ko_KR.json

@ -976,8 +976,10 @@
"support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.", "support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.",
"telemetry-topic-filter": "Telemetry topic filter", "telemetry-topic-filter": "Telemetry topic filter",
"telemetry-topic-filter-required": "Telemetry topic filter is required.", "telemetry-topic-filter-required": "Telemetry topic filter is required.",
"attributes-topic-filter": "Attributes topic filter", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Attributes topic filter is required.", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Telemetry proto schema", "telemetry-proto-schema": "Telemetry proto schema",
"telemetry-proto-schema-required": "Telemetry proto schema is required.", "telemetry-proto-schema-required": "Telemetry proto schema is required.",
"attributes-proto-schema": "Attributes proto schema", "attributes-proto-schema": "Attributes proto schema",

6
ui-ngx/src/assets/locale/locale.constant-sl_SI.json

@ -976,8 +976,10 @@
"support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.", "support-level-wildcards": "Single <code>[+]</code> and multi-level <code>[#]</code> wildcards supported.",
"telemetry-topic-filter": "Telemetry topic filter", "telemetry-topic-filter": "Telemetry topic filter",
"telemetry-topic-filter-required": "Telemetry topic filter is required.", "telemetry-topic-filter-required": "Telemetry topic filter is required.",
"attributes-topic-filter": "Attributes topic filter", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Attributes topic filter is required.", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Telemetry proto schema", "telemetry-proto-schema": "Telemetry proto schema",
"telemetry-proto-schema-required": "Telemetry proto schema is required.", "telemetry-proto-schema-required": "Telemetry proto schema is required.",
"attributes-proto-schema": "Attributes proto schema", "attributes-proto-schema": "Attributes proto schema",

6
ui-ngx/src/assets/locale/locale.constant-tr_TR.json

@ -1107,8 +1107,10 @@
"support-level-wildcards": "Tekli <code>[+]</code> ve çoklu <code>[#]</code> joker karakter destekler.", "support-level-wildcards": "Tekli <code>[+]</code> ve çoklu <code>[#]</code> joker karakter destekler.",
"telemetry-topic-filter": "Telemetri konu filtresi", "telemetry-topic-filter": "Telemetri konu filtresi",
"telemetry-topic-filter-required": "Telemetri konu filtresi gerekli.", "telemetry-topic-filter-required": "Telemetri konu filtresi gerekli.",
"attributes-topic-filter": "Öznitelikler konu filtresi", "attributes-topic-filter": "Attributes publish topic filter",
"attributes-topic-filter-required": "Öznitelikler konu filtresi gerekli.", "attributes-subscribe-topic-filter": "Attributes subscribe topic filter",
"attributes-topic-filter-required": "Attributes publish topic filter is required.",
"attributes-subscribe-topic-filter-required": "Attributes subscribe topic is required",
"telemetry-proto-schema": "Telemetri proto şeması", "telemetry-proto-schema": "Telemetri proto şeması",
"telemetry-proto-schema-required": "Telemetri proto şeması gerekli.", "telemetry-proto-schema-required": "Telemetri proto şeması gerekli.",
"attributes-proto-schema": "Öznitelikler proto şeması", "attributes-proto-schema": "Öznitelikler proto şeması",

Loading…
Cancel
Save