Browse Source

Merge remote-tracking branch 'origin/master' into feature/spring-boot-2

pull/1500/head
Volodymyr Babak 7 years ago
parent
commit
492d449ce1
  1. 2
      application/build.gradle
  2. 12
      application/pom.xml
  3. 2
      application/src/main/assembly/windows.xml
  4. 2
      application/src/main/conf/logback.xml
  5. 2
      application/src/main/conf/thingsboard.conf
  6. 4
      application/src/main/data/json/system/widget_bundles/input_widgets.json
  7. 14
      application/src/main/data/json/system/widget_bundles/maps.json
  8. 2
      application/src/main/data/upgrade/1.3.0/schema_update.cql
  9. 2
      application/src/main/data/upgrade/1.3.1/schema_update.sql
  10. 2
      application/src/main/data/upgrade/1.4.0/schema_update.cql
  11. 2
      application/src/main/data/upgrade/1.4.0/schema_update.sql
  12. 2
      application/src/main/data/upgrade/2.0.0/schema_update.cql
  13. 2
      application/src/main/data/upgrade/2.0.0/schema_update.sql
  14. 9
      application/src/main/data/upgrade/2.1.1/schema_update.cql
  15. 6
      application/src/main/data/upgrade/2.1.1/schema_update.sql
  16. 2
      application/src/main/data/upgrade/2.1.2/schema_update.cql
  17. 2
      application/src/main/data/upgrade/2.1.2/schema_update.sql
  18. 2
      application/src/main/data/upgrade/2.2.0/schema_update.sql
  19. 17
      application/src/main/data/upgrade/2.3.1/schema_update.sql
  20. 2
      application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java
  21. 2
      application/src/main/java/org/thingsboard/server/ThingsboardServerApplication.java
  22. 18
      application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
  23. 2
      application/src/main/java/org/thingsboard/server/actors/app/AppActor.java
  24. 2
      application/src/main/java/org/thingsboard/server/actors/app/AppInitMsg.java
  25. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActor.java
  26. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActorCreator.java
  27. 61
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java
  28. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActorToRuleEngineMsg.java
  29. 2
      application/src/main/java/org/thingsboard/server/actors/device/SessionInfo.java
  30. 2
      application/src/main/java/org/thingsboard/server/actors/device/SessionInfoMetaData.java
  31. 2
      application/src/main/java/org/thingsboard/server/actors/device/SessionTimeoutCheckMsg.java
  32. 2
      application/src/main/java/org/thingsboard/server/actors/device/ToDeviceRpcRequestMetadata.java
  33. 2
      application/src/main/java/org/thingsboard/server/actors/device/ToServerRpcRequestMetadata.java
  34. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/BasicRpcSessionListener.java
  35. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcBroadcastMsg.java
  36. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcManagerActor.java
  37. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionActor.java
  38. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionClosedMsg.java
  39. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionConnectedMsg.java
  40. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionCreateRequestMsg.java
  41. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionDisconnectedMsg.java
  42. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionTellMsg.java
  43. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/SessionActorInfo.java
  44. 29
      application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
  45. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java
  46. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActor.java
  47. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java
  48. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java
  49. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainToRuleChainMsg.java
  50. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainToRuleNodeMsg.java
  51. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActor.java
  52. 7
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java
  53. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeCtx.java
  54. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeRelation.java
  55. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java
  56. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToSelfErrorMsg.java
  57. 2
      application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToSelfMsg.java
  58. 2
      application/src/main/java/org/thingsboard/server/actors/service/ActorService.java
  59. 15
      application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java
  60. 2
      application/src/main/java/org/thingsboard/server/actors/service/ContextAwareActor.java
  61. 2
      application/src/main/java/org/thingsboard/server/actors/service/ContextBasedCreator.java
  62. 9
      application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java
  63. 2
      application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java
  64. 2
      application/src/main/java/org/thingsboard/server/actors/shared/ActorTerminationMsg.java
  65. 4
      application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java
  66. 2
      application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java
  67. 2
      application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java
  68. 2
      application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
  69. 2
      application/src/main/java/org/thingsboard/server/actors/shared/rulechain/TenantRuleChainManager.java
  70. 2
      application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java
  71. 2
      application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistMsg.java
  72. 2
      application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java
  73. 2
      application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
  74. 2
      application/src/main/java/org/thingsboard/server/config/AuditLogLevelProperties.java
  75. 2
      application/src/main/java/org/thingsboard/server/config/JwtSettings.java
  76. 2
      application/src/main/java/org/thingsboard/server/config/MvcCorsProperties.java
  77. 2
      application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java
  78. 3
      application/src/main/java/org/thingsboard/server/config/SchedulingConfiguration.java
  79. 5
      application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java
  80. 2
      application/src/main/java/org/thingsboard/server/config/ThingsboardMessageConfiguration.java
  81. 2
      application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
  82. 3
      application/src/main/java/org/thingsboard/server/config/ThingsboardWebFluxSecurityConfig.java
  83. 2
      application/src/main/java/org/thingsboard/server/config/WebConfig.java
  84. 4
      application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
  85. 7
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  86. 31
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  87. 39
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  88. 2
      application/src/main/java/org/thingsboard/server/controller/AuditLogController.java
  89. 2
      application/src/main/java/org/thingsboard/server/controller/AuthController.java
  90. 212
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  91. 2
      application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java
  92. 16
      application/src/main/java/org/thingsboard/server/controller/CustomerController.java
  93. 38
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  94. 43
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  95. 33
      application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java
  96. 52
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  97. 27
      application/src/main/java/org/thingsboard/server/controller/EventController.java
  98. 2
      application/src/main/java/org/thingsboard/server/controller/HttpValidationCallback.java
  99. 5
      application/src/main/java/org/thingsboard/server/controller/RpcController.java
  100. 33
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

2
application/build.gradle

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

12
application/pom.xml

@ -1,6 +1,6 @@
<!--
Copyright © 2016-2018 The Thingsboard Authors
Copyright © 2016-2019 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.2.0-SNAPSHOT</version>
<version>2.3.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<artifactId>application</artifactId>
@ -41,6 +41,10 @@
</properties>
<dependencies>
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
@ -264,6 +268,10 @@
<groupId>org.javadelight</groupId>
<artifactId>delight-nashorn-sandbox</artifactId>
</dependency>
<dependency>
<groupId>io.springfox.ui</groupId>
<artifactId>springfox-swagger-ui-rfc6570</artifactId>
</dependency>
</dependencies>
<build>

2
application/src/main/assembly/windows.xml

@ -1,6 +1,6 @@
<!--
Copyright © 2016-2018 The Thingsboard Authors
Copyright © 2016-2019 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

2
application/src/main/conf/logback.xml

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright © 2016-2018 The Thingsboard Authors
Copyright © 2016-2019 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

2
application/src/main/conf/thingsboard.conf

@ -1,5 +1,5 @@
#
# Copyright © 2016-2018 The Thingsboard Authors
# Copyright © 2016-2019 The Thingsboard Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

4
application/src/main/data/json/system/widget_bundles/input_widgets.json

@ -63,7 +63,7 @@
"resources": [],
"templateHtml": "<form class=\"attribute-update-form\"\n name=\"attrUpdateForm\"\n ng-submit=\"updateAttribute($event)\"\n>\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-checkbox ng-model=\"checkboxValue\"\n aria-label=\"Switch entity attribute value\"\n ng-change=\"changed()\"\n ng-true-value=\"'true'\"\n ng-false-value=\"'false'\"\n >\n {{currentValue}}\n </md-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\" ng-bind=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n No attribute is selected\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n Timeseries parameter cannot be used in this widget\n </div>\n </div>\n</form>",
"templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.entity-title {\n font-weight: bold;\n font-size: 22px;\n padding-top: 12px;\n padding-bottom: 6px;\n color: #666;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .md-icon-button md-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}",
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n \n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:\"true\", [settings.falseValue]:\"false\"};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.server.value,\n [\n {\n key: $scope.currentKey,\n value: $scope.currentValue\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n $scope.checkboxValue = mapReverse[$scope.originalValue = self.ctx.data[0].data[0][1]] || 'false';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {\n\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {\n\n}\n",
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n\n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:true, [settings.falseValue]:false};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.server.value,\n [\n {\n key: $scope.currentKey,\n value: mapReverse[$scope.currentValue] || false\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n try {\n if ($scope.dataKeyDetected) {\n $scope.checkboxValue = ($scope.originalValue = self.ctx.data[0].data[0][1]) || false;\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onResize = function() {}\nself.onDestroy = function() {}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"trueValue\": {\n \"title\": \"True value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"falseValue\": {\n \"title\": \"False value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showResultMessage\",\n \"trueValue\",\n \"falseValue\"\n ]\n}",
"dataKeySettingsSchema": "{}\n",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update server boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
@ -127,7 +127,7 @@
"resources": [],
"templateHtml": "<form class=\"attribute-update-form\"\n name=\"attrUpdateForm\"\n ng-submit=\"updateAttribute($event)\"\n>\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-checkbox ng-model=\"checkboxValue\"\n aria-label=\"Switch entity attribute value\"\n ng-change=\"changed()\"\n ng-true-value=\"'true'\"\n ng-false-value=\"'false'\"\n >\n {{currentValue}}\n </md-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\" ng-bind=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n No attribute is selected\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n Timeseries parameter cannot be used in this widget\n </div>\n </div>\n</form>",
"templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.entity-title {\n font-weight: bold;\n font-size: 22px;\n padding-top: 12px;\n padding-bottom: 6px;\n color: #666;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n.grid__element:last-child {\n margin-top: 19px;\n margin-left: 7px;\n}\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .md-icon-button md-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}",
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n \n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:\"true\", [settings.falseValue]:\"false\"};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n \n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType === \"DEVICE\") {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n } else {\n $scope.message = 'Selected entity cannot have shared attributes';\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.shared.value,\n [\n {\n key: $scope.currentKey,\n value: $scope.currentValue\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n\n try {\n $scope.checkboxValue = mapReverse[$scope.originalValue = self.ctx.data[0].data[0][1]] || 'false';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {\n\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {\n\n}\n",
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n\n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:true, [settings.falseValue]:false};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType === \"DEVICE\") {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n } else {\n $scope.message = 'Selected entity cannot have shared attributes';\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.shared.value,\n [\n {\n key: $scope.currentKey,\n value: mapReverse[$scope.currentValue] || false\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n try {\n $scope.checkboxValue = ($scope.originalValue = self.ctx.data[0].data[0][1]) || 'false';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n\n } catch (e) {\n console.log(e);\n }\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onResize = function() {}\nself.onDestroy = function() {}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"trueValue\": {\n \"title\": \"True value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"falseValue\": {\n \"title\": \"False value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showResultMessage\",\n \"trueValue\",\n \"falseValue\"\n ]\n}",
"dataKeySettingsSchema": "{}\n",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"trueValue\":\"active\",\"falseValue\":\"inactive\"},\"title\":\"Update shared boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"

14
application/src/main/data/json/system/widget_bundles/maps.json

File diff suppressed because one or more lines are too long

2
application/src/main/data/upgrade/1.3.0/schema_update.cql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/1.3.1/schema_update.sql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/1.4.0/schema_update.cql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/1.4.0/schema_update.sql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/2.0.0/schema_update.cql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/2.0.0/schema_update.sql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

9
application/src/main/data/upgrade/2.1.1/schema_update.cql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
@ -14,13 +14,6 @@
-- limitations under the License.
--
DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_name;
DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_search_text;
DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_customer;
DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_entity_id;
DROP TABLE IF EXISTS thingsboard.entity_views;
CREATE TABLE IF NOT EXISTS thingsboard.entity_views (
id timeuuid,
entity_id timeuuid,

6
application/src/main/data/upgrade/2.1.1/schema_update.sql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
@ -14,10 +14,8 @@
-- limitations under the License.
--
DROP TABLE IF EXISTS entity_views;
CREATE TABLE IF NOT EXISTS entity_views (
id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY,
id varchar(31) NOT NULL CONSTRAINT entity_views_pkey PRIMARY KEY,
entity_id varchar(31),
entity_type varchar(255),
tenant_id varchar(31),

2
application/src/main/data/upgrade/2.1.2/schema_update.cql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/2.1.2/schema_update.sql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

2
application/src/main/data/upgrade/2.2.0/schema_update.sql

@ -1,5 +1,5 @@
--
-- Copyright © 2016-2018 The Thingsboard Authors
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.

17
application/src/main/data/upgrade/2.3.1/schema_update.sql

@ -0,0 +1,17 @@
--
-- Copyright © 2016-2019 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
ALTER TABLE event ALTER COLUMN body SET DATA TYPE varchar(10000000);

2
application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/ThingsboardServerApplication.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

18
application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -34,6 +34,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.thingsboard.rule.engine.api.MailService;
import org.thingsboard.rule.engine.api.RuleChainTransactionService;
import org.thingsboard.server.actors.service.ActorService;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Event;
@ -48,6 +49,7 @@ import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.audit.AuditLogService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.event.EventService;
@ -65,6 +67,7 @@ import org.thingsboard.server.service.encoding.DataDecodingEncodingService;
import org.thingsboard.server.service.executors.ClusterRpcCallbackExecutorService;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.executors.ExternalCallExecutorService;
import org.thingsboard.server.service.executors.SharedEventLoopGroupService;
import org.thingsboard.server.service.mail.MailExecutorService;
import org.thingsboard.server.service.rpc.DeviceRpcService;
import org.thingsboard.server.service.script.JsExecutorService;
@ -124,6 +127,10 @@ public class ActorSystemContext {
@Getter
private AssetService assetService;
@Autowired
@Getter
private DashboardService dashboardService;
@Autowired
@Getter
private TenantService tenantService;
@ -200,6 +207,10 @@ public class ActorSystemContext {
@Getter
private ExternalCallExecutorService externalCallExecutorService;
@Autowired
@Getter
private SharedEventLoopGroupService sharedEventLoopGroupService;
@Autowired
@Getter
private MailService mailService;
@ -217,6 +228,11 @@ public class ActorSystemContext {
@Getter
private RuleEngineTransportService ruleEngineTransportService;
@Lazy
@Autowired
@Getter
private RuleChainTransactionService ruleChainTransactionService;
@Value("${cluster.partition_id}")
@Getter
private long queuePartitionId;

2
application/src/main/java/org/thingsboard/server/actors/app/AppActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/app/AppInitMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/DeviceActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/DeviceActorCreator.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

61
application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
package org.thingsboard.server.actors.device;
import akka.actor.ActorContext;
import akka.event.LoggingAdapter;
import com.datastax.driver.core.utils.UUIDs;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
@ -26,12 +25,12 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.thingsboard.rule.engine.api.RpcError;
import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg;
import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -42,7 +41,6 @@ import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.cluster.ClusterEventMsg;
import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg;
@ -81,12 +79,14 @@ import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.DataConstants.CLIENT_SCOPE;
import static org.thingsboard.server.common.data.DataConstants.SHARED_SCOPE;
/**
* @author Andrew Shvayka
*/
@ -263,10 +263,8 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
}
private void handleGetAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) {
ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, toOptionalSet(request.getClientAttributeNamesList()));
ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, toOptionalSet(request.getSharedAttributeNamesList()));
int requestId = request.getRequestId();
Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback<List<List<AttributeKvEntry>>>() {
Futures.addCallback(getAttributesKvEntries(request), new FutureCallback<List<List<AttributeKvEntry>>>() {
@Override
public void onSuccess(@Nullable List<List<AttributeKvEntry>> result) {
GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder()
@ -287,16 +285,35 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
});
}
private ListenableFuture<List<AttributeKvEntry>> getAttributeKvEntries(DeviceId deviceId, String scope, Optional<Set<String>> names) {
if (names.isPresent()) {
if (!names.get().isEmpty()) {
return systemContext.getAttributesService().find(tenantId, deviceId, scope, names.get());
} else {
return systemContext.getAttributesService().findAll(tenantId, deviceId, scope);
}
private ListenableFuture<List<List<AttributeKvEntry>>> getAttributesKvEntries(GetAttributeRequestMsg request) {
ListenableFuture<List<AttributeKvEntry>> clientAttributesFuture;
ListenableFuture<List<AttributeKvEntry>> sharedAttributesFuture;
if (CollectionUtils.isEmpty(request.getClientAttributeNamesList()) && CollectionUtils.isEmpty(request.getSharedAttributeNamesList())) {
clientAttributesFuture = findAllAttributesByScope(CLIENT_SCOPE);
sharedAttributesFuture = findAllAttributesByScope(SHARED_SCOPE);
} else if (!CollectionUtils.isEmpty(request.getClientAttributeNamesList()) && !CollectionUtils.isEmpty(request.getSharedAttributeNamesList())) {
clientAttributesFuture = findAttributesByScope(toSet(request.getClientAttributeNamesList()), CLIENT_SCOPE);
sharedAttributesFuture = findAttributesByScope(toSet(request.getSharedAttributeNamesList()), SHARED_SCOPE);
} else if (CollectionUtils.isEmpty(request.getClientAttributeNamesList()) && !CollectionUtils.isEmpty(request.getSharedAttributeNamesList())) {
clientAttributesFuture = Futures.immediateFuture(Collections.emptyList());
sharedAttributesFuture = findAttributesByScope(toSet(request.getSharedAttributeNamesList()), SHARED_SCOPE);
} else {
return Futures.immediateFuture(Collections.emptyList());
sharedAttributesFuture = Futures.immediateFuture(Collections.emptyList());
clientAttributesFuture = findAttributesByScope(toSet(request.getClientAttributeNamesList()), CLIENT_SCOPE);
}
return Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture));
}
private ListenableFuture<List<AttributeKvEntry>> findAllAttributesByScope(String scope) {
return systemContext.getAttributesService().findAll(tenantId, deviceId, scope);
}
private ListenableFuture<List<AttributeKvEntry>> findAttributesByScope(Set<String> attributesSet, String scope) {
return systemContext.getAttributesService().find(tenantId, deviceId, scope, attributesSet);
}
private Set<String> toSet(List<String> strings) {
return new HashSet<>(strings);
}
private void handlePostAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, PostAttributeMsg postAttributes) {
@ -368,7 +385,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
AttributeUpdateNotificationMsg.Builder notification = AttributeUpdateNotificationMsg.newBuilder();
if (msg.isDeleted()) {
List<String> sharedKeys = msg.getDeletedKeys().stream()
.filter(key -> DataConstants.SHARED_SCOPE.equals(key.getScope()))
.filter(key -> SHARED_SCOPE.equals(key.getScope()))
.map(AttributeKey::getAttributeKey)
.collect(Collectors.toList());
if (!sharedKeys.isEmpty()) {
@ -376,7 +393,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
hasNotificationData = true;
}
} else {
if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) {
if (SHARED_SCOPE.equals(msg.getScope())) {
List<AttributeKvEntry> attributes = new ArrayList<>(msg.getValues());
if (attributes.size() > 0) {
List<TsKvProto> sharedUpdated = msg.getValues().stream().map(this::toTsKvProto)
@ -545,14 +562,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
return json;
}
private Optional<Set<String>> toOptionalSet(List<String> strings) {
if (strings == null || strings.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(new HashSet<>(strings));
}
}
private void sendToTransport(GetAttributeResponseMsg responseMsg, SessionInfoProto sessionInfo) {
DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder()
.setSessionIdMSB(sessionInfo.getSessionIdMSB())

2
application/src/main/java/org/thingsboard/server/actors/device/DeviceActorToRuleEngineMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/SessionInfo.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/SessionInfoMetaData.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/SessionTimeoutCheckMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/ToDeviceRpcRequestMetadata.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/device/ToServerRpcRequestMetadata.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/BasicRpcSessionListener.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcBroadcastMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcManagerActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionClosedMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionConnectedMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionCreateRequestMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionDisconnectedMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionTellMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/rpc/SessionActorInfo.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

29
application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,9 +17,11 @@ package org.thingsboard.server.actors.ruleChain;
import akka.actor.ActorRef;
import com.datastax.driver.core.utils.UUIDs;
import io.netty.channel.EventLoopGroup;
import org.springframework.util.StringUtils;
import org.thingsboard.rule.engine.api.ListeningExecutor;
import org.thingsboard.rule.engine.api.MailService;
import org.thingsboard.rule.engine.api.RuleChainTransactionService;
import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcRequest;
import org.thingsboard.rule.engine.api.RuleEngineDeviceRpcResponse;
import org.thingsboard.rule.engine.api.RuleEngineRpcService;
@ -43,6 +45,7 @@ import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.relation.RelationService;
@ -54,6 +57,7 @@ import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
import scala.concurrent.duration.Duration;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@ -99,6 +103,12 @@ class DefaultTbContext implements TbContext {
scheduleMsgWithDelay(new RuleNodeToSelfMsg(msg), delayMs, nodeCtx.getSelfActor());
}
@Override
public boolean isLocalEntity(EntityId entityId) {
Optional<ServerAddress> address = mainCtx.getRoutingService().resolveById(entityId);
return !address.isPresent();
}
private void scheduleMsgWithDelay(Object msg, long delayInMs, ActorRef target) {
mainCtx.getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, mainCtx.getActorSystem().dispatcher(), nodeCtx.getSelfActor());
}
@ -123,7 +133,7 @@ class DefaultTbContext implements TbContext {
@Override
public TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) {
return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), mainCtx.getQueuePartitionId());
return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), origMsg.getDataType(), data, origMsg.getTransactionData(), origMsg.getRuleChainId(), origMsg.getRuleNodeId(), mainCtx.getQueuePartitionId());
}
@Override
@ -196,6 +206,11 @@ class DefaultTbContext implements TbContext {
return mainCtx.getDeviceService();
}
@Override
public DashboardService getDashboardService() {
return mainCtx.getDashboardService();
}
@Override
public AlarmService getAlarmService() {
return mainCtx.getAlarmService();
@ -226,6 +241,16 @@ class DefaultTbContext implements TbContext {
return mainCtx.getEntityViewService();
}
@Override
public RuleChainTransactionService getRuleChainTransactionService() {
return mainCtx.getRuleChainTransactionService();
}
@Override
public EventLoopGroup getSharedEventLoop() {
return mainCtx.getSharedEventLoopGroupService().getSharedEventLoopGroup();
}
@Override
public MailService getMailService() {
if (mainCtx.isAllowSystemMailService()) {

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainToRuleChainMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainToRuleNodeMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

7
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@ package org.thingsboard.server.actors.ruleChain;
import akka.actor.ActorContext;
import akka.actor.ActorRef;
import akka.event.LoggingAdapter;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
@ -84,7 +83,9 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
@Override
public void onClusterEventMsg(ClusterEventMsg msg) {
if (tbNode != null) {
tbNode.onClusterEventMsg(defaultCtx, msg);
}
}
public void onRuleToSelfMsg(RuleNodeToSelfMsg msg) throws Exception {

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeCtx.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeRelation.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToSelfErrorMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToSelfMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/service/ActorService.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

15
application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,9 +16,6 @@
package org.thingsboard.server.actors.service;
import akka.actor.ActorRef;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
import org.thingsboard.server.actors.stats.StatsPersistMsg;
@ -60,7 +57,8 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP
scheduleStatsPersistTick();
}
} catch (Exception e) {
log.warn("[{}][{}] Failed to start {} processor: {}", tenantId, id, id.getEntityType(), e);
log.warn("[{}][{}] Failed to start {} processor.", tenantId, id, id.getEntityType());
log.warn("Error:", e);
logAndPersist("OnStart", e, true);
logLifecycleEvent(ComponentLifecycleEvent.STARTED, e);
}
@ -149,10 +147,13 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP
private void logAndPersist(String method, Exception e, boolean critical) {
errorsOccurred++;
String componentName = processor != null ? processor.getComponentName() : "Unknown";
if (critical) {
log.warn("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, processor.getComponentName(), method, e);
log.warn("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, componentName, method);
log.warn("Critical Error: ", e);
} else {
log.debug("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, processor.getComponentName(), method, e);
log.debug("[{}][{}][{}] Failed to process {} msg: {}", id, tenantId, componentName, method);
log.debug("Debug Error: ", e);
}
long ts = System.currentTimeMillis();
if (ts - lastPersistedErrorTs > getErrorPersistFrequency()) {

2
application/src/main/java/org/thingsboard/server/actors/service/ContextAwareActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/service/ContextBasedCreator.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

9
application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -56,12 +56,8 @@ import scala.concurrent.duration.Duration;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static org.thingsboard.server.gen.cluster.ClusterAPIProtos.MessageType.CLUSTER_ACTOR_MESSAGE;
@ -235,6 +231,9 @@ public class DefaultActorService implements ActorService {
case CLUSTER_DEVICE_STATE_SERVICE_MESSAGE:
actorContext.getDeviceStateService().onRemoteMsg(serverAddress, msg.getPayload().toByteArray());
break;
case CLUSTER_TRANSACTION_SERVICE_MESSAGE:
actorContext.getRuleChainTransactionService().onRemoteTransactionMsg(serverAddress, msg.getPayload().toByteArray());
break;
}
}

2
application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/shared/ActorTerminationMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

4
application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -83,7 +83,7 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract
protected void checkActive() {
if (state != ComponentLifecycleState.ACTIVE) {
log.warn("Rule chain is not active. Current state [{}] for processor [{}] tenant [{}]", state, tenantId, entityId);
log.debug("Component is not active. Current state [{}] for processor [{}][{}] tenant [{}]", state, entityId.getEntityType(), entityId, tenantId);
throw new IllegalStateException("Rule chain is not active! " + entityId + " - " + tenantId);
}
}

2
application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/TenantRuleChainManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/config/AuditLogLevelProperties.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/config/JwtSettings.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/config/MvcCorsProperties.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

3
application/src/main/java/org/thingsboard/server/config/SchedulingConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.config;
import org.springframework.context.annotation.Bean;

5
application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -64,7 +64,8 @@ public class SwaggerConfiguration {
.paths(apiPaths())
.build()
.securitySchemes(newArrayList(jwtTokenKey()))
.securityContexts(newArrayList(securityContext()));
.securityContexts(newArrayList(securityContext()))
.enableUrlTemplating(true);
}
private ApiKey jwtTokenKey() {

2
application/src/main/java/org/thingsboard/server/config/ThingsboardMessageConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

2
application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

3
application/src/main/java/org/thingsboard/server/config/ThingsboardWebFluxSecurityConfig.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.config;
import org.springframework.beans.factory.annotation.Autowired;

2
application/src/main/java/org/thingsboard/server/config/WebConfig.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

4
application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -44,7 +44,6 @@ import java.util.Map;
public class WebSocketConfiguration {
public static final String WS_PLUGIN_PREFIX = "/api/ws/plugins/";
public static final String WS_SECURITY_USER_ATTRIBUTE = "SECURITY_USER";
private static final String WS_PLUGIN_MAPPING = WS_PLUGIN_PREFIX + "**";
/* @Bean
@ -87,7 +86,6 @@ public class WebSocketConfiguration {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return false;
} else {
attributes.put(WS_SECURITY_USER_ATTRIBUTE, user);
return true;
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,6 +28,8 @@ import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import org.thingsboard.server.service.update.UpdateService;
import org.thingsboard.server.service.update.model.UpdateMessage;
@ -49,6 +51,7 @@ public class AdminController extends BaseController {
@ResponseBody
public AdminSettings getAdminSettings(@PathVariable("key") String key) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key));
} catch (Exception e) {
throw handleException(e);
@ -60,6 +63,7 @@ public class AdminController extends BaseController {
@ResponseBody
public AdminSettings saveAdminSettings(@RequestBody AdminSettings adminSettings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
if (adminSettings.getKey().equals("mail")) {
mailService.updateMailConfiguration();
@ -74,6 +78,7 @@ public class AdminController extends BaseController {
@RequestMapping(value = "/settings/testMail", method = RequestMethod.POST)
public void sendTestMail(@RequestBody AdminSettings adminSettings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
adminSettings = checkNotNull(adminSettings);
if (adminSettings.getKey().equals("mail")) {
String email = getCurrentUser().getEmail();

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
@RestController
@RequestMapping("/api")
@ -55,7 +57,7 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId);
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
return checkAlarmId(alarmId);
return checkAlarmId(alarmId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -68,7 +70,7 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId);
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
return checkAlarmInfoId(alarmId);
return checkAlarmInfoId(alarmId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -80,6 +82,8 @@ public class AlarmController extends BaseController {
public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException {
try {
alarm.setTenantId(getCurrentUser().getTenantId());
Operation operation = alarm.getId() == null ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarm.getId(), alarm);
Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm));
logEntityAction(savedAlarm.getId(), savedAlarm,
getCurrentUser().getCustomerId(),
@ -92,6 +96,19 @@ public class AlarmController extends BaseController {
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE)
@ResponseBody
public Boolean deleteAlarm(@PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException {
checkParameter(ALARM_ID, strAlarmId);
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
return alarmService.deleteAlarm(getTenantId(), alarmId);
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ -99,7 +116,7 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId);
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
Alarm alarm = checkAlarmId(alarmId);
Alarm alarm = checkAlarmId(alarmId, Operation.WRITE);
alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, System.currentTimeMillis()).get();
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null);
} catch (Exception e) {
@ -114,7 +131,7 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId);
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
Alarm alarm = checkAlarmId(alarmId);
Alarm alarm = checkAlarmId(alarmId, Operation.WRITE);
alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, System.currentTimeMillis()).get();
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null);
} catch (Exception e) {
@ -146,7 +163,7 @@ public class AlarmController extends BaseController {
throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " +
"and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
try {
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get());
@ -173,7 +190,7 @@ public class AlarmController extends BaseController {
throw new ThingsboardException("Invalid alarms search query: Both parameters 'searchStatus' " +
"and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
try {
return alarmService.findHighestAlarmSeverity(getCurrentUser().getTenantId(), entityId, alarmSearchStatus, alarmStatus);
} catch (Exception e) {

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -43,6 +43,8 @@ import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.util.ArrayList;
import java.util.List;
@ -61,7 +63,7 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
return checkAssetId(assetId);
return checkAssetId(assetId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -73,15 +75,12 @@ public class AssetController extends BaseController {
public Asset saveAsset(@RequestBody Asset asset) throws ThingsboardException {
try {
asset.setTenantId(getCurrentUser().getTenantId());
if (getCurrentUser().getAuthority() == Authority.CUSTOMER_USER) {
if (asset.getId() == null || asset.getId().isNullUid() ||
asset.getCustomerId() == null || asset.getCustomerId().isNullUid()) {
throw new ThingsboardException("You don't have permission to perform this operation!",
ThingsboardErrorCode.PERMISSION_DENIED);
} else {
checkCustomerId(asset.getCustomerId());
}
}
Operation operation = asset.getId() == null ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, operation,
asset.getId(), asset);
Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
logEntityAction(savedAsset.getId(), savedAsset,
@ -103,7 +102,7 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
Asset asset = checkAssetId(assetId);
Asset asset = checkAssetId(assetId, Operation.DELETE);
assetService.deleteAsset(getTenantId(), assetId);
logEntityAction(assetId, asset,
@ -128,10 +127,10 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
AssetId assetId = new AssetId(toUUID(strAssetId));
checkAssetId(assetId);
checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER);
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(getTenantId(), assetId, customerId));
@ -157,12 +156,12 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
Asset asset = checkAssetId(assetId);
Asset asset = checkAssetId(assetId, Operation.UNASSIGN_FROM_CUSTOMER);
if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
throw new IncorrectParameterException("Asset isn't assigned to any customer!");
}
Customer customer = checkCustomerId(asset.getCustomerId());
Customer customer = checkCustomerId(asset.getCustomerId(), Operation.READ);
Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(getTenantId(), assetId));
@ -188,7 +187,7 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
Asset asset = checkAssetId(assetId);
Asset asset = checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(asset.getTenantId());
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(getTenantId(), assetId, publicCustomer.getId()));
@ -256,7 +255,7 @@ public class AssetController extends BaseController {
try {
TenantId tenantId = getCurrentUser().getTenantId();
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
checkCustomerId(customerId, Operation.READ);
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
if (type != null && type.trim().length()>0) {
return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
@ -301,12 +300,12 @@ public class AssetController extends BaseController {
checkNotNull(query);
checkNotNull(query.getParameters());
checkNotNull(query.getAssetTypes());
checkEntityId(query.getParameters().getEntityId());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
List<Asset> assets = checkNotNull(assetService.findAssetsByQuery(getTenantId(), query).get());
assets = assets.stream().filter(asset -> {
try {
checkAsset(asset);
accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, Operation.READ, asset.getId(), asset);
return true;
} catch (ThingsboardException e) {
return false;

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

212
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
@ -74,6 +75,9 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.AccessControlService;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import org.thingsboard.server.service.state.DeviceStateService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
@ -98,6 +102,9 @@ public abstract class BaseController {
@Autowired
private ThingsboardErrorResponseHandler errorResponseHandler;
@Autowired
protected AccessControlService accessControlService;
@Autowired
protected TenantService tenantService;
@ -252,13 +259,15 @@ public abstract class BaseController {
}
}
void checkTenantId(TenantId tenantId) throws ThingsboardException {
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
SecurityUser authUser = getCurrentUser();
if (authUser.getAuthority() != Authority.SYS_ADMIN &&
(authUser.getTenantId() == null || !authUser.getTenantId().equals(tenantId))) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
Tenant checkTenantId(TenantId tenantId, Operation operation) throws ThingsboardException {
try {
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Tenant tenant = tenantService.findTenantById(tenantId);
checkNotNull(tenant);
accessControlService.checkPermission(getCurrentUser(), Resource.TENANT, operation, tenantId, tenant);
return tenant;
} catch (Exception e) {
throw handleException(e, false);
}
}
@ -266,80 +275,61 @@ public abstract class BaseController {
return getCurrentUser().getTenantId();
}
Customer checkCustomerId(CustomerId customerId) throws ThingsboardException {
Customer checkCustomerId(CustomerId customerId, Operation operation) throws ThingsboardException {
try {
SecurityUser authUser = getCurrentUser();
if (authUser.getAuthority() == Authority.SYS_ADMIN ||
(authUser.getAuthority() != Authority.TENANT_ADMIN &&
(authUser.getCustomerId() == null || !authUser.getCustomerId().equals(customerId)))) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
if (customerId != null && !customerId.isNullUid()) {
Customer customer = customerService.findCustomerById(authUser.getTenantId(), customerId);
checkCustomer(customer);
return customer;
} else {
return null;
}
validateId(customerId, "Incorrect customerId " + customerId);
Customer customer = customerService.findCustomerById(getTenantId(), customerId);
checkNotNull(customer);
accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customerId, customer);
return customer;
} catch (Exception e) {
throw handleException(e, false);
}
}
private void checkCustomer(Customer customer) throws ThingsboardException {
checkNotNull(customer);
checkTenantId(customer.getTenantId());
}
User checkUserId(UserId userId) throws ThingsboardException {
User checkUserId(UserId userId, Operation operation) throws ThingsboardException {
try {
validateId(userId, "Incorrect userId " + userId);
User user = userService.findUserById(getCurrentUser().getTenantId(), userId);
checkUser(user);
checkNotNull(user);
accessControlService.checkPermission(getCurrentUser(), Resource.USER, operation, userId, user);
return user;
} catch (Exception e) {
throw handleException(e, false);
}
}
private void checkUser(User user) throws ThingsboardException {
checkNotNull(user);
checkTenantId(user.getTenantId());
if (user.getAuthority() == Authority.CUSTOMER_USER) {
checkCustomerId(user.getCustomerId());
}
}
protected void checkEntityId(EntityId entityId) throws ThingsboardException {
protected void checkEntityId(EntityId entityId, Operation operation) throws ThingsboardException {
try {
checkNotNull(entityId);
validateId(entityId.getId(), "Incorrect entityId " + entityId);
SecurityUser authUser = getCurrentUser();
switch (entityId.getEntityType()) {
case DEVICE:
checkDevice(deviceService.findDeviceById(authUser.getTenantId(), new DeviceId(entityId.getId())));
checkDeviceId(new DeviceId(entityId.getId()), operation);
return;
case CUSTOMER:
checkCustomerId(new CustomerId(entityId.getId()));
checkCustomerId(new CustomerId(entityId.getId()), operation);
return;
case TENANT:
checkTenantId(new TenantId(entityId.getId()));
checkTenantId(new TenantId(entityId.getId()), operation);
return;
case RULE_CHAIN:
checkRuleChain(new RuleChainId(entityId.getId()));
checkRuleChain(new RuleChainId(entityId.getId()), operation);
return;
case RULE_NODE:
checkRuleNode(new RuleNodeId(entityId.getId()), operation);
return;
case ASSET:
checkAsset(assetService.findAssetById(authUser.getTenantId(), new AssetId(entityId.getId())));
checkAssetId(new AssetId(entityId.getId()), operation);
return;
case DASHBOARD:
checkDashboardId(new DashboardId(entityId.getId()));
checkDashboardId(new DashboardId(entityId.getId()), operation);
return;
case USER:
checkUserId(new UserId(entityId.getId()));
checkUserId(new UserId(entityId.getId()), operation);
return;
case ENTITY_VIEW:
checkEntityViewId(new EntityViewId(entityId.getId()));
checkEntityViewId(new EntityViewId(entityId.getId()), operation);
return;
default:
throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType());
@ -349,160 +339,114 @@ public abstract class BaseController {
}
}
Device checkDeviceId(DeviceId deviceId) throws ThingsboardException {
Device checkDeviceId(DeviceId deviceId, Operation operation) throws ThingsboardException {
try {
validateId(deviceId, "Incorrect deviceId " + deviceId);
Device device = deviceService.findDeviceById(getCurrentUser().getTenantId(), deviceId);
checkDevice(device);
checkNotNull(device);
accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, operation, deviceId, device);
return device;
} catch (Exception e) {
throw handleException(e, false);
}
}
protected void checkDevice(Device device) throws ThingsboardException {
checkNotNull(device);
checkTenantId(device.getTenantId());
checkCustomerId(device.getCustomerId());
}
protected EntityView checkEntityViewId(EntityViewId entityViewId) throws ThingsboardException {
protected EntityView checkEntityViewId(EntityViewId entityViewId, Operation operation) throws ThingsboardException {
try {
validateId(entityViewId, "Incorrect entityViewId " + entityViewId);
EntityView entityView = entityViewService.findEntityViewById(getCurrentUser().getTenantId(), entityViewId);
checkEntityView(entityView);
checkNotNull(entityView);
accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, operation, entityViewId, entityView);
return entityView;
} catch (Exception e) {
throw handleException(e, false);
}
}
protected void checkEntityView(EntityView entityView) throws ThingsboardException {
checkNotNull(entityView);
checkTenantId(entityView.getTenantId());
checkCustomerId(entityView.getCustomerId());
}
Asset checkAssetId(AssetId assetId) throws ThingsboardException {
Asset checkAssetId(AssetId assetId, Operation operation) throws ThingsboardException {
try {
validateId(assetId, "Incorrect assetId " + assetId);
Asset asset = assetService.findAssetById(getCurrentUser().getTenantId(), assetId);
checkAsset(asset);
checkNotNull(asset);
accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, operation, assetId, asset);
return asset;
} catch (Exception e) {
throw handleException(e, false);
}
}
protected void checkAsset(Asset asset) throws ThingsboardException {
checkNotNull(asset);
checkTenantId(asset.getTenantId());
checkCustomerId(asset.getCustomerId());
}
Alarm checkAlarmId(AlarmId alarmId) throws ThingsboardException {
Alarm checkAlarmId(AlarmId alarmId, Operation operation) throws ThingsboardException {
try {
validateId(alarmId, "Incorrect alarmId " + alarmId);
Alarm alarm = alarmService.findAlarmByIdAsync(getCurrentUser().getTenantId(), alarmId).get();
checkAlarm(alarm);
checkNotNull(alarm);
accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarmId, alarm);
return alarm;
} catch (Exception e) {
throw handleException(e, false);
}
}
AlarmInfo checkAlarmInfoId(AlarmId alarmId) throws ThingsboardException {
AlarmInfo checkAlarmInfoId(AlarmId alarmId, Operation operation) throws ThingsboardException {
try {
validateId(alarmId, "Incorrect alarmId " + alarmId);
AlarmInfo alarmInfo = alarmService.findAlarmInfoByIdAsync(getCurrentUser().getTenantId(), alarmId).get();
checkAlarm(alarmInfo);
checkNotNull(alarmInfo);
accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarmId, alarmInfo);
return alarmInfo;
} catch (Exception e) {
throw handleException(e, false);
}
}
protected void checkAlarm(Alarm alarm) throws ThingsboardException {
checkNotNull(alarm);
checkTenantId(alarm.getTenantId());
}
WidgetsBundle checkWidgetsBundleId(WidgetsBundleId widgetsBundleId, boolean modify) throws ThingsboardException {
WidgetsBundle checkWidgetsBundleId(WidgetsBundleId widgetsBundleId, Operation operation) throws ThingsboardException {
try {
validateId(widgetsBundleId, "Incorrect widgetsBundleId " + widgetsBundleId);
WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleById(getCurrentUser().getTenantId(), widgetsBundleId);
checkWidgetsBundle(widgetsBundle, modify);
checkNotNull(widgetsBundle);
accessControlService.checkPermission(getCurrentUser(), Resource.WIDGETS_BUNDLE, operation, widgetsBundleId, widgetsBundle);
return widgetsBundle;
} catch (Exception e) {
throw handleException(e, false);
}
}
private void checkWidgetsBundle(WidgetsBundle widgetsBundle, boolean modify) throws ThingsboardException {
checkNotNull(widgetsBundle);
if (widgetsBundle.getTenantId() != null && !widgetsBundle.getTenantId().getId().equals(ModelConstants.NULL_UUID)) {
checkTenantId(widgetsBundle.getTenantId());
} else if (modify && getCurrentUser().getAuthority() != Authority.SYS_ADMIN) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
}
WidgetType checkWidgetTypeId(WidgetTypeId widgetTypeId, boolean modify) throws ThingsboardException {
WidgetType checkWidgetTypeId(WidgetTypeId widgetTypeId, Operation operation) throws ThingsboardException {
try {
validateId(widgetTypeId, "Incorrect widgetTypeId " + widgetTypeId);
WidgetType widgetType = widgetTypeService.findWidgetTypeById(getCurrentUser().getTenantId(), widgetTypeId);
checkWidgetType(widgetType, modify);
checkNotNull(widgetType);
accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, operation, widgetTypeId, widgetType);
return widgetType;
} catch (Exception e) {
throw handleException(e, false);
}
}
void checkWidgetType(WidgetType widgetType, boolean modify) throws ThingsboardException {
checkNotNull(widgetType);
if (widgetType.getTenantId() != null && !widgetType.getTenantId().getId().equals(ModelConstants.NULL_UUID)) {
checkTenantId(widgetType.getTenantId());
} else if (modify && getCurrentUser().getAuthority() != Authority.SYS_ADMIN) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
}
Dashboard checkDashboardId(DashboardId dashboardId) throws ThingsboardException {
Dashboard checkDashboardId(DashboardId dashboardId, Operation operation) throws ThingsboardException {
try {
validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
Dashboard dashboard = dashboardService.findDashboardById(getCurrentUser().getTenantId(), dashboardId);
checkDashboard(dashboard);
checkNotNull(dashboard);
accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation, dashboardId, dashboard);
return dashboard;
} catch (Exception e) {
throw handleException(e, false);
}
}
DashboardInfo checkDashboardInfoId(DashboardId dashboardId) throws ThingsboardException {
DashboardInfo checkDashboardInfoId(DashboardId dashboardId, Operation operation) throws ThingsboardException {
try {
validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(getCurrentUser().getTenantId(), dashboardId);
checkDashboard(dashboardInfo);
checkNotNull(dashboardInfo);
accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation, dashboardId, dashboardInfo);
return dashboardInfo;
} catch (Exception e) {
throw handleException(e, false);
}
}
private void checkDashboard(DashboardInfo dashboard) throws ThingsboardException {
checkNotNull(dashboard);
checkTenantId(dashboard.getTenantId());
SecurityUser authUser = getCurrentUser();
if (authUser.getAuthority() == Authority.CUSTOMER_USER) {
if (!dashboard.isAssignedToCustomer(authUser.getCustomerId())) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
}
}
ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException {
try {
log.debug("[{}] Lookup component descriptor", clazz);
@ -530,24 +474,22 @@ public abstract class BaseController {
}
}
protected RuleChain checkRuleChain(RuleChainId ruleChainId) throws ThingsboardException {
checkNotNull(ruleChainId);
return checkRuleChain(ruleChainService.findRuleChainById(getCurrentUser().getTenantId(), ruleChainId));
}
protected RuleChain checkRuleChain(RuleChain ruleChain) throws ThingsboardException {
protected RuleChain checkRuleChain(RuleChainId ruleChainId, Operation operation) throws ThingsboardException {
validateId(ruleChainId, "Incorrect ruleChainId " + ruleChainId);
RuleChain ruleChain = ruleChainService.findRuleChainById(getCurrentUser().getTenantId(), ruleChainId);
checkNotNull(ruleChain);
SecurityUser authUser = getCurrentUser();
TenantId tenantId = ruleChain.getTenantId();
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
if (authUser.getAuthority() != Authority.TENANT_ADMIN ||
!authUser.getTenantId().equals(tenantId)) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
accessControlService.checkPermission(getCurrentUser(), Resource.RULE_CHAIN, operation, ruleChainId, ruleChain);
return ruleChain;
}
protected RuleNode checkRuleNode(RuleNodeId ruleNodeId, Operation operation) throws ThingsboardException {
validateId(ruleNodeId, "Incorrect ruleNodeId " + ruleNodeId);
RuleNode ruleNode = ruleChainService.findRuleNodeById(getTenantId(), ruleNodeId);
checkNotNull(ruleNode);
checkRuleChain(ruleNode.getRuleChainId(), operation);
return ruleNode;
}
protected String constructBaseUrl(HttpServletRequest request) {
String scheme = request.getScheme();

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,6 +36,8 @@ import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
@RestController
@RequestMapping("/api")
@ -51,7 +53,7 @@ public class CustomerController extends BaseController {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
return checkCustomerId(customerId);
return checkCustomerId(customerId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -64,7 +66,7 @@ public class CustomerController extends BaseController {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode infoObject = objectMapper.createObjectNode();
infoObject.put("title", customer.getTitle());
@ -82,7 +84,7 @@ public class CustomerController extends BaseController {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
return customer.getTitle();
} catch (Exception e) {
throw handleException(e);
@ -95,6 +97,10 @@ public class CustomerController extends BaseController {
public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException {
try {
customer.setTenantId(getCurrentUser().getTenantId());
Operation operation = customer.getId() == null ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customer.getId(), customer);
Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer));
logEntityAction(savedCustomer.getId(), savedCustomer,
@ -118,7 +124,7 @@ public class CustomerController extends BaseController {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.DELETE);
customerService.deleteCustomer(getTenantId(), customerId);
logEntityAction(customerId, customer,

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.util.HashSet;
import java.util.Set;
@ -76,7 +78,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
return checkDashboardInfoId(dashboardId);
return checkDashboardInfoId(dashboardId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -89,7 +91,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
return checkDashboardId(dashboardId);
return checkDashboardId(dashboardId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -101,6 +103,12 @@ public class DashboardController extends BaseController {
public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException {
try {
dashboard.setTenantId(getCurrentUser().getTenantId());
Operation operation = dashboard.getId() == null ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation,
dashboard.getId(), dashboard);
Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard));
logEntityAction(savedDashboard.getId(), savedDashboard,
@ -123,7 +131,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.DELETE);
dashboardService.deleteDashboard(getCurrentUser().getTenantId(), dashboardId);
logEntityAction(dashboardId, dashboard,
@ -150,10 +158,10 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
checkDashboardId(dashboardId);
checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER);
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(getCurrentUser().getTenantId(), dashboardId, customerId));
@ -182,9 +190,9 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.UNASSIGN_FROM_CUSTOMER);
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(getCurrentUser().getTenantId(), dashboardId, customerId));
@ -211,7 +219,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER);
Set<CustomerId> customerIds = new HashSet<>();
if (strCustomerIds != null) {
@ -276,7 +284,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER);
Set<CustomerId> customerIds = new HashSet<>();
if (strCustomerIds != null) {
@ -319,7 +327,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.UNASSIGN_FROM_CUSTOMER);
Set<CustomerId> customerIds = new HashSet<>();
if (strCustomerIds != null) {
@ -362,7 +370,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId());
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(getCurrentUser().getTenantId(), dashboardId, publicCustomer.getId()));
@ -388,7 +396,7 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId, Operation.UNASSIGN_FROM_CUSTOMER);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId());
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(getCurrentUser().getTenantId(), dashboardId, publicCustomer.getId()));
@ -419,7 +427,7 @@ public class DashboardController extends BaseController {
@RequestParam(required = false) String textOffset) throws ThingsboardException {
try {
TenantId tenantId = new TenantId(toUUID(strTenantId));
checkTenantId(tenantId);
checkTenantId(tenantId, Operation.READ);
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink));
} catch (Exception e) {
@ -458,7 +466,7 @@ public class DashboardController extends BaseController {
try {
TenantId tenantId = getCurrentUser().getTenantId();
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
checkCustomerId(customerId, Operation.READ);
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink).get());
} catch (Exception e) {

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -44,6 +44,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.util.ArrayList;
import java.util.List;
@ -62,7 +64,7 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
return checkDeviceId(deviceId);
return checkDeviceId(deviceId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -74,15 +76,12 @@ public class DeviceController extends BaseController {
public Device saveDevice(@RequestBody Device device) throws ThingsboardException {
try {
device.setTenantId(getCurrentUser().getTenantId());
if (getCurrentUser().getAuthority() == Authority.CUSTOMER_USER) {
if (device.getId() == null || device.getId().isNullUid() ||
device.getCustomerId() == null || device.getCustomerId().isNullUid()) {
throw new ThingsboardException("You don't have permission to perform this operation!",
ThingsboardErrorCode.PERMISSION_DENIED);
} else {
checkCustomerId(device.getCustomerId());
}
}
Operation operation = device.getId() == null ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, operation,
device.getId(), device);
Device savedDevice = checkNotNull(deviceService.saveDevice(device));
actorService
@ -116,7 +115,7 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
Device device = checkDeviceId(deviceId);
Device device = checkDeviceId(deviceId, Operation.DELETE);
deviceService.deleteDevice(getCurrentUser().getTenantId(), deviceId);
logEntityAction(deviceId, device,
@ -142,10 +141,10 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
checkDeviceId(deviceId);
checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER);
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(getCurrentUser().getTenantId(), deviceId, customerId));
@ -169,11 +168,11 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
Device device = checkDeviceId(deviceId);
Device device = checkDeviceId(deviceId, Operation.UNASSIGN_FROM_CUSTOMER);
if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
throw new IncorrectParameterException("Device isn't assigned to any customer!");
}
Customer customer = checkCustomerId(device.getCustomerId());
Customer customer = checkCustomerId(device.getCustomerId(), Operation.READ);
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(getCurrentUser().getTenantId(), deviceId));
@ -197,7 +196,7 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
Device device = checkDeviceId(deviceId);
Device device = checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(device.getTenantId());
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(getCurrentUser().getTenantId(), deviceId, publicCustomer.getId()));
@ -221,7 +220,7 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
Device device = checkDeviceId(deviceId);
Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS);
DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(getCurrentUser().getTenantId(), deviceId));
logEntityAction(deviceId, device,
device.getCustomerId(),
@ -241,7 +240,7 @@ public class DeviceController extends BaseController {
public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException {
checkNotNull(deviceCredentials);
try {
Device device = checkDeviceId(deviceCredentials.getDeviceId());
Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS);
DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials));
actorService.onCredentialsUpdate(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId());
logEntityAction(device.getId(), device,
@ -305,7 +304,7 @@ public class DeviceController extends BaseController {
try {
TenantId tenantId = getCurrentUser().getTenantId();
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
checkCustomerId(customerId, Operation.READ);
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
if (type != null && type.trim().length() > 0) {
return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink));
@ -350,12 +349,12 @@ public class DeviceController extends BaseController {
checkNotNull(query);
checkNotNull(query.getParameters());
checkNotNull(query.getDeviceTypes());
checkEntityId(query.getParameters().getEntityId());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
List<Device> devices = checkNotNull(deviceService.findDevicesByQuery(getCurrentUser().getTenantId(), query).get());
devices = devices.stream().filter(device -> {
try {
checkDevice(device);
accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, Operation.READ, device.getId(), device);
return true;
} catch (ThingsboardException e) {
return false;

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.EntityRelationInfo;
import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.service.security.permission.Operation;
import java.util.List;
@ -55,8 +56,8 @@ public class EntityRelationController extends BaseController {
public void saveRelation(@RequestBody EntityRelation relation) throws ThingsboardException {
try {
checkNotNull(relation);
checkEntityId(relation.getFrom());
checkEntityId(relation.getTo());
checkEntityId(relation.getFrom(), Operation.WRITE);
checkEntityId(relation.getTo(), Operation.WRITE);
if (relation.getTypeGroup() == null) {
relation.setTypeGroup(RelationTypeGroup.COMMON);
}
@ -89,8 +90,8 @@ public class EntityRelationController extends BaseController {
checkParameter(TO_TYPE, strToType);
EntityId fromId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(fromId);
checkEntityId(toId);
checkEntityId(fromId, Operation.WRITE);
checkEntityId(toId, Operation.WRITE);
RelationTypeGroup relationTypeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
EntityRelation relation = new EntityRelation(fromId, toId, strRelationType, relationTypeGroup);
try {
@ -119,7 +120,7 @@ public class EntityRelationController extends BaseController {
checkParameter("entityId", strId);
checkParameter("entityType", strType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strType, strId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.WRITE);
try {
relationService.deleteEntityRelations(getTenantId(), entityId);
logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, null);
@ -145,8 +146,8 @@ public class EntityRelationController extends BaseController {
checkParameter(TO_TYPE, strToType);
EntityId fromId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
EntityId toId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(fromId);
checkEntityId(toId);
checkEntityId(fromId, Operation.READ);
checkEntityId(toId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
return checkNotNull(relationService.getRelation(getTenantId(), fromId, toId, strRelationType, typeGroup));
} catch (Exception e) {
@ -163,7 +164,7 @@ public class EntityRelationController extends BaseController {
checkParameter(FROM_ID, strFromId);
checkParameter(FROM_TYPE, strFromType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByFrom(getTenantId(), entityId, typeGroup));
@ -181,7 +182,7 @@ public class EntityRelationController extends BaseController {
checkParameter(FROM_ID, strFromId);
checkParameter(FROM_TYPE, strFromType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findInfoByFrom(getTenantId(), entityId, typeGroup).get());
@ -201,7 +202,7 @@ public class EntityRelationController extends BaseController {
checkParameter(FROM_TYPE, strFromType);
checkParameter(RELATION_TYPE, strRelationType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strFromType, strFromId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByFromAndType(getTenantId(), entityId, strRelationType, typeGroup));
@ -219,7 +220,7 @@ public class EntityRelationController extends BaseController {
checkParameter(TO_ID, strToId);
checkParameter(TO_TYPE, strToType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByTo(getTenantId(), entityId, typeGroup));
@ -237,7 +238,7 @@ public class EntityRelationController extends BaseController {
checkParameter(TO_ID, strToId);
checkParameter(TO_TYPE, strToType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findInfoByTo(getTenantId(), entityId, typeGroup).get());
@ -257,7 +258,7 @@ public class EntityRelationController extends BaseController {
checkParameter(TO_TYPE, strToType);
checkParameter(RELATION_TYPE, strRelationType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
checkEntityId(entityId);
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByToAndType(getTenantId(), entityId, strRelationType, typeGroup));
@ -273,7 +274,7 @@ public class EntityRelationController extends BaseController {
checkNotNull(query);
checkNotNull(query.getParameters());
checkNotNull(query.getFilters());
checkEntityId(query.getParameters().getEntityId());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
return checkNotNull(relationService.findByQuery(getTenantId(), query).get());
} catch (Exception e) {
@ -288,7 +289,7 @@ public class EntityRelationController extends BaseController {
checkNotNull(query);
checkNotNull(query.getParameters());
checkNotNull(query.getFilters());
checkEntityId(query.getParameters().getEntityId());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
return checkNotNull(relationService.findInfoByQuery(getTenantId(), query).get());
} catch (Exception e) {

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -48,6 +48,8 @@ import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import javax.annotation.Nullable;
import java.util.ArrayList;
@ -74,7 +76,7 @@ public class EntityViewController extends BaseController {
public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try {
return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)));
return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -86,6 +88,12 @@ public class EntityViewController extends BaseController {
public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException {
try {
entityView.setTenantId(getCurrentUser().getTenantId());
Operation operation = entityView.getId() == null ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, operation,
entityView.getId(), entityView);
EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView));
List<ListenableFuture<List<Void>>> futures = new ArrayList<>();
if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) {
@ -168,7 +176,7 @@ public class EntityViewController extends BaseController {
checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try {
EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
EntityView entityView = checkEntityViewId(entityViewId);
EntityView entityView = checkEntityViewId(entityViewId, Operation.DELETE);
entityViewService.deleteEntityView(getTenantId(), entityViewId);
logEntityAction(entityViewId, entityView, entityView.getCustomerId(),
ActionType.DELETED, null, strEntityViewId);
@ -203,10 +211,10 @@ public class EntityViewController extends BaseController {
checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId, Operation.READ);
EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
checkEntityViewId(entityViewId);
checkEntityViewId(entityViewId, Operation.ASSIGN_TO_CUSTOMER);
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(getTenantId(), entityViewId, customerId));
logEntityAction(entityViewId, savedEntityView,
@ -228,11 +236,11 @@ public class EntityViewController extends BaseController {
checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try {
EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
EntityView entityView = checkEntityViewId(entityViewId);
EntityView entityView = checkEntityViewId(entityViewId, Operation.UNASSIGN_FROM_CUSTOMER);
if (entityView.getCustomerId() == null || entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
throw new IncorrectParameterException("Entity View isn't assigned to any customer!");
}
Customer customer = checkCustomerId(entityView.getCustomerId());
Customer customer = checkCustomerId(entityView.getCustomerId(), Operation.READ);
EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(getTenantId(), entityViewId));
logEntityAction(entityViewId, entityView,
entityView.getCustomerId(),
@ -261,7 +269,7 @@ public class EntityViewController extends BaseController {
try {
TenantId tenantId = getCurrentUser().getTenantId();
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
checkCustomerId(customerId, Operation.READ);
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
if (type != null && type.trim().length() > 0) {
return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type));
@ -303,12 +311,12 @@ public class EntityViewController extends BaseController {
checkNotNull(query);
checkNotNull(query.getParameters());
checkNotNull(query.getEntityViewTypes());
checkEntityId(query.getParameters().getEntityId());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
List<EntityView> entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(getTenantId(), query).get());
entityViews = entityViews.stream().filter(entityView -> {
try {
checkEntityView(entityView);
accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, Operation.READ, entityView.getId(), entityView);
return true;
} catch (ThingsboardException e) {
return false;
@ -333,4 +341,28 @@ public class EntityViewController extends BaseController {
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/entityView/{entityViewId}", method = RequestMethod.POST)
@ResponseBody
public EntityView assignEntityViewToPublicCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
checkParameter(ENTITY_VIEW_ID, strEntityViewId);
try {
EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
EntityView entityView = checkEntityViewId(entityViewId, Operation.ASSIGN_TO_CUSTOMER);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(entityView.getTenantId());
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(getCurrentUser().getTenantId(), entityViewId, publicCustomer.getId()));
logEntityAction(entityViewId, savedEntityView,
savedEntityView.getCustomerId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, publicCustomer.getId().toString(), publicCustomer.getName());
return savedEntityView;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strEntityViewId);
throw handleException(e);
}
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,12 +26,15 @@ import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
@RestController
@RequestMapping("/api")
@ -58,13 +61,12 @@ public class EventController extends BaseController {
checkParameter("EntityType", strEntityType);
try {
TenantId tenantId = new TenantId(toUUID(strTenantId));
if (!tenantId.getId().equals(ModelConstants.NULL_UUID) &&
!tenantId.equals(getCurrentUser().getTenantId())) {
throw new ThingsboardException("You don't have permission to perform this operation!",
ThingsboardErrorCode.PERMISSION_DENIED);
}
EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
checkEntityId(entityId, Operation.READ);
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(eventService.findEvents(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), eventType, pageLink));
return checkNotNull(eventService.findEvents(tenantId, entityId, eventType, pageLink));
} catch (Exception e) {
throw handleException(e);
}
@ -87,13 +89,12 @@ public class EventController extends BaseController {
checkParameter("EntityType", strEntityType);
try {
TenantId tenantId = new TenantId(toUUID(strTenantId));
if (!tenantId.getId().equals(ModelConstants.NULL_UUID) &&
!tenantId.equals(getCurrentUser().getTenantId())) {
throw new ThingsboardException("You don't have permission to perform this operation!",
ThingsboardErrorCode.PERMISSION_DENIED);
}
EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId);
checkEntityId(entityId, Operation.READ);
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(eventService.findEvents(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), pageLink));
return checkNotNull(eventService.findEvents(tenantId, entityId, pageLink));
} catch (Exception e) {
throw handleException(e);
}

2
application/src/main/java/org/thingsboard/server/controller/HttpValidationCallback.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

5
application/src/main/java/org/thingsboard/server/controller/RpcController.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -47,6 +47,7 @@ import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
import org.thingsboard.server.service.rpc.LocalRequestMetaData;
import org.thingsboard.server.service.security.AccessValidator;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.telemetry.exception.ToErrorResponseEntity;
import javax.annotation.Nullable;
@ -118,7 +119,7 @@ public class RpcController extends BaseController {
final DeferredResult<ResponseEntity> response = new DeferredResult<>();
long timeout = System.currentTimeMillis() + (cmd.getTimeout() != null ? cmd.getTimeout() : DEFAULT_TIMEOUT);
ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(cmd.getMethodName(), cmd.getRequestData());
accessValidator.validate(currentUser, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() {
accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() {
@Override
public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
ToDeviceRpcRequest rpcRequest = new ToDeviceRpcRequest(UUID.randomUUID(),

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2018 The Thingsboard Authors
* Copyright © 2016-2019 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -47,15 +47,20 @@ import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.service.script.JsInvokeService;
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@RestController
@ -80,7 +85,7 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_CHAIN_ID, strRuleChainId);
try {
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
return checkRuleChain(ruleChainId);
return checkRuleChain(ruleChainId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -93,7 +98,7 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_CHAIN_ID, strRuleChainId);
try {
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
checkRuleChain(ruleChainId);
checkRuleChain(ruleChainId, Operation.READ);
return ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChainId);
} catch (Exception e) {
throw handleException(e);
@ -108,6 +113,12 @@ public class RuleChainController extends BaseController {
try {
boolean created = ruleChain.getId() == null;
ruleChain.setTenantId(getCurrentUser().getTenantId());
Operation operation = created ? Operation.CREATE : Operation.WRITE;
accessControlService.checkPermission(getCurrentUser(), Resource.RULE_CHAIN, operation,
ruleChain.getId(), ruleChain);
RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
actorService.onEntityStateChange(ruleChain.getTenantId(), savedRuleChain.getId(),
@ -134,7 +145,7 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_CHAIN_ID, strRuleChainId);
try {
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChain ruleChain = checkRuleChain(ruleChainId);
RuleChain ruleChain = checkRuleChain(ruleChainId, Operation.WRITE);
TenantId tenantId = getCurrentUser().getTenantId();
RuleChain previousRootRuleChain = ruleChainService.getRootTenantRuleChain(tenantId);
if (ruleChainService.setRootRuleChain(getTenantId(), ruleChainId)) {
@ -171,7 +182,7 @@ public class RuleChainController extends BaseController {
@ResponseBody
public RuleChainMetaData saveRuleChainMetaData(@RequestBody RuleChainMetaData ruleChainMetaData) throws ThingsboardException {
try {
RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId());
RuleChain ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE);
RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.saveRuleChainMetaData(getTenantId(), ruleChainMetaData));
actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);
@ -214,10 +225,19 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_CHAIN_ID, strRuleChainId);
try {
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChain ruleChain = checkRuleChain(ruleChainId);
RuleChain ruleChain = checkRuleChain(ruleChainId, Operation.DELETE);
List<RuleNode> referencingRuleNodes = ruleChainService.getReferencingRuleChainNodes(getTenantId(), ruleChainId);
Set<RuleChainId> referencingRuleChainIds = referencingRuleNodes.stream().map(RuleNode::getRuleChainId).collect(Collectors.toSet());
ruleChainService.deleteRuleChainById(getTenantId(), ruleChainId);
referencingRuleChainIds.remove(ruleChain.getId());
referencingRuleChainIds.forEach(referencingRuleChainId ->
actorService.onEntityStateChange(ruleChain.getTenantId(), referencingRuleChainId, ComponentLifecycleEvent.UPDATED));
actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.DELETED);
logEntityAction(ruleChainId, ruleChain,
@ -240,6 +260,7 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_NODE_ID, strRuleNodeId);
try {
RuleNodeId ruleNodeId = new RuleNodeId(toUUID(strRuleNodeId));
checkRuleNode(ruleNodeId, Operation.READ);
TenantId tenantId = getCurrentUser().getTenantId();
List<Event> events = eventService.findLatestEvents(tenantId, ruleNodeId, DataConstants.DEBUG_RULE_NODE, 2);
JsonNode result = null;

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save