Commit 0a82a8309ef04e658257be792a1ad096aa6a8f85

Authored by Igor Kulikov
2 parents 75351e35 1b469df4

Merge branch 'master' into feature/TB-61

@@ -326,7 +326,19 @@ public final class PluginProcessingContext implements PluginContext { @@ -326,7 +326,19 @@ public final class PluginProcessingContext implements PluginContext {
326 callback.onSuccess(this, Boolean.FALSE); 326 callback.onSuccess(this, Boolean.FALSE);
327 } else { 327 } else {
328 ListenableFuture<RuleMetaData> ruleFuture = pluginCtx.ruleService.findRuleByIdAsync(new RuleId(entityId.getId())); 328 ListenableFuture<RuleMetaData> ruleFuture = pluginCtx.ruleService.findRuleByIdAsync(new RuleId(entityId.getId()));
329 - Futures.addCallback(ruleFuture, getCallback(callback, rule -> rule != null && rule.getTenantId().equals(ctx.getTenantId()))); 329 + Futures.addCallback(ruleFuture, getCallback(callback, rule -> {
  330 + if (rule == null) {
  331 + return Boolean.FALSE;
  332 + } else {
  333 + if (ctx.isTenantAdmin() && !rule.getTenantId().equals(ctx.getTenantId())) {
  334 + return Boolean.FALSE;
  335 + } else if (ctx.isSystemAdmin() && !rule.getTenantId().isNullUid()) {
  336 + return Boolean.FALSE;
  337 + } else {
  338 + return Boolean.TRUE;
  339 + }
  340 + }
  341 + }));
330 } 342 }
331 return; 343 return;
332 case PLUGIN: 344 case PLUGIN:
@@ -334,7 +346,19 @@ public final class PluginProcessingContext implements PluginContext { @@ -334,7 +346,19 @@ public final class PluginProcessingContext implements PluginContext {
334 callback.onSuccess(this, Boolean.FALSE); 346 callback.onSuccess(this, Boolean.FALSE);
335 } else { 347 } else {
336 ListenableFuture<PluginMetaData> pluginFuture = pluginCtx.pluginService.findPluginByIdAsync(new PluginId(entityId.getId())); 348 ListenableFuture<PluginMetaData> pluginFuture = pluginCtx.pluginService.findPluginByIdAsync(new PluginId(entityId.getId()));
337 - Futures.addCallback(pluginFuture, getCallback(callback, plugin -> plugin != null && plugin.getTenantId().equals(ctx.getTenantId()))); 349 + Futures.addCallback(pluginFuture, getCallback(callback, plugin -> {
  350 + if (plugin == null) {
  351 + return Boolean.FALSE;
  352 + } else {
  353 + if (ctx.isTenantAdmin() && !plugin.getTenantId().equals(ctx.getTenantId())) {
  354 + return Boolean.FALSE;
  355 + } else if (ctx.isSystemAdmin() && !plugin.getTenantId().isNullUid()) {
  356 + return Boolean.FALSE;
  357 + } else {
  358 + return Boolean.TRUE;
  359 + }
  360 + }
  361 + }));
338 } 362 }
339 return; 363 return;
340 case CUSTOMER: 364 case CUSTOMER:
@@ -91,4 +91,13 @@ public class DeviceAttributes { @@ -91,4 +91,13 @@ public class DeviceAttributes {
91 } 91 }
92 return map; 92 return map;
93 } 93 }
  94 +
  95 + @Override
  96 + public String toString() {
  97 + return "DeviceAttributes{" +
  98 + "clientSideAttributesMap=" + clientSideAttributesMap +
  99 + ", serverPrivateAttributesMap=" + serverPrivateAttributesMap +
  100 + ", serverPublicAttributesMap=" + serverPublicAttributesMap +
  101 + '}';
  102 + }
94 } 103 }
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.extensions.core.action.template; 16 package org.thingsboard.server.extensions.core.action.template;
17 17
  18 +import lombok.extern.slf4j.Slf4j;
18 import org.apache.velocity.Template; 19 import org.apache.velocity.Template;
19 import org.apache.velocity.VelocityContext; 20 import org.apache.velocity.VelocityContext;
20 import org.apache.velocity.runtime.parser.ParseException; 21 import org.apache.velocity.runtime.parser.ParseException;
@@ -35,6 +36,7 @@ import java.util.Optional; @@ -35,6 +36,7 @@ import java.util.Optional;
35 /** 36 /**
36 * @author Andrew Shvayka 37 * @author Andrew Shvayka
37 */ 38 */
  39 +@Slf4j
38 public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfiguration> extends SimpleRuleLifecycleComponent implements PluginAction<T> { 40 public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfiguration> extends SimpleRuleLifecycleComponent implements PluginAction<T> {
39 protected T configuration; 41 protected T configuration;
40 protected Template template; 42 protected Template template;
@@ -69,6 +71,7 @@ public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfi @@ -69,6 +71,7 @@ public abstract class AbstractTemplatePluginAction<T extends TemplateActionConfi
69 } 71 }
70 72
71 protected String getMsgBody(RuleContext ctx, ToDeviceActorMsg msg) { 73 protected String getMsgBody(RuleContext ctx, ToDeviceActorMsg msg) {
  74 + log.trace("Creating context for: {} and payload {}", ctx.getDeviceAttributes(), msg.getPayload());
72 VelocityContext context = VelocityUtils.createContext(ctx.getDeviceAttributes(), msg.getPayload()); 75 VelocityContext context = VelocityUtils.createContext(ctx.getDeviceAttributes(), msg.getPayload());
73 return VelocityUtils.merge(template, context); 76 return VelocityUtils.merge(template, context);
74 } 77 }
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.extensions.kafka.plugin; 16 package org.thingsboard.server.extensions.kafka.plugin;
17 17
18 import lombok.RequiredArgsConstructor; 18 import lombok.RequiredArgsConstructor;
  19 +import lombok.extern.slf4j.Slf4j;
19 import org.apache.kafka.clients.producer.Producer; 20 import org.apache.kafka.clients.producer.Producer;
20 import org.apache.kafka.clients.producer.ProducerRecord; 21 import org.apache.kafka.clients.producer.ProducerRecord;
21 import org.thingsboard.server.common.data.id.RuleId; 22 import org.thingsboard.server.common.data.id.RuleId;
@@ -30,6 +31,7 @@ import org.thingsboard.server.extensions.kafka.action.KafkaActionMsg; @@ -30,6 +31,7 @@ import org.thingsboard.server.extensions.kafka.action.KafkaActionMsg;
30 import org.thingsboard.server.extensions.kafka.action.KafkaActionPayload; 31 import org.thingsboard.server.extensions.kafka.action.KafkaActionPayload;
31 32
32 @RequiredArgsConstructor 33 @RequiredArgsConstructor
  34 +@Slf4j
33 public class KafkaMsgHandler implements RuleMsgHandler { 35 public class KafkaMsgHandler implements RuleMsgHandler {
34 36
35 private final Producer<?, String> producer; 37 private final Producer<?, String> producer;
@@ -40,7 +42,7 @@ public class KafkaMsgHandler implements RuleMsgHandler { @@ -40,7 +42,7 @@ public class KafkaMsgHandler implements RuleMsgHandler {
40 throw new RuleException("Unsupported message type " + msg.getClass().getName() + "!"); 42 throw new RuleException("Unsupported message type " + msg.getClass().getName() + "!");
41 } 43 }
42 KafkaActionPayload payload = ((KafkaActionMsg) msg).getPayload(); 44 KafkaActionPayload payload = ((KafkaActionMsg) msg).getPayload();
43 - 45 + log.debug("Processing kafka payload: {}", payload);
44 try { 46 try {
45 producer.send(new ProducerRecord<>(payload.getTopic(), payload.getMsgBody()), 47 producer.send(new ProducerRecord<>(payload.getTopic(), payload.getMsgBody()),
46 (metadata, e) -> { 48 (metadata, e) -> {
@@ -78,6 +78,7 @@ public class GatewaySessionCtx { @@ -78,6 +78,7 @@ public class GatewaySessionCtx {
78 Device newDevice = new Device(); 78 Device newDevice = new Device();
79 newDevice.setTenantId(gateway.getTenantId()); 79 newDevice.setTenantId(gateway.getTenantId());
80 newDevice.setName(deviceName); 80 newDevice.setName(deviceName);
  81 + newDevice.setType("default");
81 return deviceService.saveDevice(newDevice); 82 return deviceService.saveDevice(newDevice);
82 }); 83 });
83 GatewayDeviceSessionCtx ctx = new GatewayDeviceSessionCtx(this, device); 84 GatewayDeviceSessionCtx ctx = new GatewayDeviceSessionCtx(this, device);
@@ -51,7 +51,6 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS @@ -51,7 +51,6 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS
51 scope.types = types; 51 scope.types = types;
52 52
53 scope.entityType = attrs.entityType; 53 scope.entityType = attrs.entityType;
54 - scope.attributeScope = getAttributeScopeByValue(attrs.defaultAttributeScope);  
55 54
56 if (scope.entityType === types.entityType.device) { 55 if (scope.entityType === types.entityType.device) {
57 scope.attributeScopes = types.attributesScope; 56 scope.attributeScopes = types.attributesScope;
@@ -60,8 +59,13 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS @@ -60,8 +59,13 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS
60 scope.attributeScopes = {}; 59 scope.attributeScopes = {};
61 scope.attributeScopes.server = types.attributesScope.server; 60 scope.attributeScopes.server = types.attributesScope.server;
62 scope.attributeScopeSelectionReadonly = true; 61 scope.attributeScopeSelectionReadonly = true;
  62 + }
  63 +
  64 + scope.attributeScope = getAttributeScopeByValue(attrs.defaultAttributeScope);
  65 +
  66 + if (scope.entityType != types.entityType.device) {
63 if (scope.attributeScope != types.latestTelemetry) { 67 if (scope.attributeScope != types.latestTelemetry) {
64 - scope.attributeScope = scope.attributeScopes.server.value; 68 + scope.attributeScope = scope.attributeScopes.server;
65 } 69 }
66 } 70 }
67 71
@@ -81,8 +85,8 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS @@ -81,8 +85,8 @@ export default function AttributeTableDirective($compile, $templateCache, $rootS
81 search: null 85 search: null
82 }; 86 };
83 87
84 - scope.$watch("entityId", function(newVal, prevVal) {  
85 - if (newVal && !angular.equals(newVal, prevVal)) { 88 + scope.$watch("entityId", function(newVal) {
  89 + if (newVal) {
86 scope.resetFilter(); 90 scope.resetFilter();
87 scope.getEntityAttributes(false, true); 91 scope.getEntityAttributes(false, true);
88 } 92 }
@@ -190,7 +190,7 @@ export default angular.module('thingsboard.locale', []) @@ -190,7 +190,7 @@ export default angular.module('thingsboard.locale', [])
190 "attribute": { 190 "attribute": {
191 "attributes": "Attributes", 191 "attributes": "Attributes",
192 "latest-telemetry": "Latest telemetry", 192 "latest-telemetry": "Latest telemetry",
193 - "attributes-scope": "Device attributes scope", 193 + "attributes-scope": "Entity attributes scope",
194 "scope-latest-telemetry": "Latest telemetry", 194 "scope-latest-telemetry": "Latest telemetry",
195 "scope-client": "Client attributes", 195 "scope-client": "Client attributes",
196 "scope-server": "Server attributes", 196 "scope-server": "Server attributes",
@@ -138,6 +138,8 @@ export default function PluginController(pluginService, userService, importExpor @@ -138,6 +138,8 @@ export default function PluginController(pluginService, userService, importExpor
138 vm.pluginGridConfig.topIndex = $stateParams.topIndex; 138 vm.pluginGridConfig.topIndex = $stateParams.topIndex;
139 } 139 }
140 140
  141 + vm.isPluginEditable = isPluginEditable;
  142 +
141 vm.activatePlugin = activatePlugin; 143 vm.activatePlugin = activatePlugin;
142 vm.suspendPlugin = suspendPlugin; 144 vm.suspendPlugin = suspendPlugin;
143 vm.exportPlugin = exportPlugin; 145 vm.exportPlugin = exportPlugin;
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <details-buttons tb-help="vm.helpLinkIdForPlugin()" help-container-id="help-container"> 19 <details-buttons tb-help="vm.helpLinkIdForPlugin()" help-container-id="help-container">
20 <div id="help-container"></div> 20 <div id="help-container"></div>
21 </details-buttons> 21 </details-buttons>
22 - <md-tabs ng-class="{'tb-headless': vm.grid.detailsConfig.isDetailsEditMode}" 22 + <md-tabs ng-class="{'tb-headless': (vm.grid.detailsConfig.isDetailsEditMode || !vm.isPluginEditable(vm.grid.operatingItem()))}"
23 id="tabs" md-border-bottom flex class="tb-absolute-fill"> 23 id="tabs" md-border-bottom flex class="tb-absolute-fill">
24 <md-tab label="{{ 'plugin.details' | translate }}"> 24 <md-tab label="{{ 'plugin.details' | translate }}">
25 <tb-plugin plugin="vm.grid.operatingItem()" 25 <tb-plugin plugin="vm.grid.operatingItem()"
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 on-export-plugin="vm.exportPlugin(event, vm.grid.detailsConfig.currentItem)" 31 on-export-plugin="vm.exportPlugin(event, vm.grid.detailsConfig.currentItem)"
32 on-delete-plugin="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-plugin> 32 on-delete-plugin="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-plugin>
33 </md-tab> 33 </md-tab>
34 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'attribute.attributes' | translate }}"> 34 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" label="{{ 'attribute.attributes' | translate }}">
35 <tb-attribute-table flex 35 <tb-attribute-table flex
36 entity-id="vm.grid.operatingItem().id.id" 36 entity-id="vm.grid.operatingItem().id.id"
37 entity-type="{{vm.types.entityType.plugin}}" 37 entity-type="{{vm.types.entityType.plugin}}"
@@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
39 default-attribute-scope="{{vm.types.attributesScope.server.value}}"> 39 default-attribute-scope="{{vm.types.attributesScope.server.value}}">
40 </tb-attribute-table> 40 </tb-attribute-table>
41 </md-tab> 41 </md-tab>
42 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'attribute.latest-telemetry' | translate }}"> 42 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" label="{{ 'attribute.latest-telemetry' | translate }}">
43 <tb-attribute-table flex 43 <tb-attribute-table flex
44 entity-id="vm.grid.operatingItem().id.id" 44 entity-id="vm.grid.operatingItem().id.id"
45 entity-type="{{vm.types.entityType.plugin}}" 45 entity-type="{{vm.types.entityType.plugin}}"
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 disable-attribute-scope-selection="true"> 48 disable-attribute-scope-selection="true">
49 </tb-attribute-table> 49 </tb-attribute-table>
50 </md-tab> 50 </md-tab>
51 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'plugin.events' | translate }}"> 51 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" label="{{ 'plugin.events' | translate }}">
52 <tb-event-table flex entity-type="vm.types.entityType.plugin" 52 <tb-event-table flex entity-type="vm.types.entityType.plugin"
53 entity-id="vm.grid.operatingItem().id.id" 53 entity-id="vm.grid.operatingItem().id.id"
54 tenant-id="vm.grid.operatingItem().tenantId.id" 54 tenant-id="vm.grid.operatingItem().tenantId.id"
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 disabled-event-types="{{vm.types.eventType.alarm.value}}"> 56 disabled-event-types="{{vm.types.eventType.alarm.value}}">
57 </tb-event-table> 57 </tb-event-table>
58 </md-tab> 58 </md-tab>
59 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'relation.relations' | translate }}"> 59 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" label="{{ 'relation.relations' | translate }}">
60 <tb-relation-table flex 60 <tb-relation-table flex
61 entity-id="vm.grid.operatingItem().id.id" 61 entity-id="vm.grid.operatingItem().id.id"
62 entity-type="{{vm.types.entityType.plugin}}"> 62 entity-type="{{vm.types.entityType.plugin}}">
@@ -134,6 +134,8 @@ export default function RuleController(ruleService, userService, importExport, $ @@ -134,6 +134,8 @@ export default function RuleController(ruleService, userService, importExport, $
134 vm.ruleGridConfig.topIndex = $stateParams.topIndex; 134 vm.ruleGridConfig.topIndex = $stateParams.topIndex;
135 } 135 }
136 136
  137 + vm.isRuleEditable = isRuleEditable;
  138 +
137 vm.activateRule = activateRule; 139 vm.activateRule = activateRule;
138 vm.suspendRule = suspendRule; 140 vm.suspendRule = suspendRule;
139 vm.exportRule = exportRule; 141 vm.exportRule = exportRule;
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <details-buttons tb-help="'rules'" help-container-id="help-container"> 19 <details-buttons tb-help="'rules'" help-container-id="help-container">
20 <div id="help-container"></div> 20 <div id="help-container"></div>
21 </details-buttons> 21 </details-buttons>
22 - <md-tabs ng-class="{'tb-headless': vm.grid.detailsConfig.isDetailsEditMode}" 22 + <md-tabs ng-class="{'tb-headless': (vm.grid.detailsConfig.isDetailsEditMode || !vm.isRuleEditable(vm.grid.operatingItem()))}"
23 id="tabs" md-border-bottom flex class="tb-absolute-fill"> 23 id="tabs" md-border-bottom flex class="tb-absolute-fill">
24 <md-tab label="{{ 'rule.details' | translate }}"> 24 <md-tab label="{{ 'rule.details' | translate }}">
25 <tb-rule rule="vm.grid.operatingItem()" 25 <tb-rule rule="vm.grid.operatingItem()"
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 on-export-rule="vm.exportRule(event, vm.grid.detailsConfig.currentItem)" 31 on-export-rule="vm.exportRule(event, vm.grid.detailsConfig.currentItem)"
32 on-delete-rule="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-rule> 32 on-delete-rule="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-rule>
33 </md-tab> 33 </md-tab>
34 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'attribute.attributes' | translate }}"> 34 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" label="{{ 'attribute.attributes' | translate }}">
35 <tb-attribute-table flex 35 <tb-attribute-table flex
36 entity-id="vm.grid.operatingItem().id.id" 36 entity-id="vm.grid.operatingItem().id.id"
37 entity-type="{{vm.types.entityType.rule}}" 37 entity-type="{{vm.types.entityType.rule}}"
@@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
39 default-attribute-scope="{{vm.types.attributesScope.server.value}}"> 39 default-attribute-scope="{{vm.types.attributesScope.server.value}}">
40 </tb-attribute-table> 40 </tb-attribute-table>
41 </md-tab> 41 </md-tab>
42 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'attribute.latest-telemetry' | translate }}"> 42 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" label="{{ 'attribute.latest-telemetry' | translate }}">
43 <tb-attribute-table flex 43 <tb-attribute-table flex
44 entity-id="vm.grid.operatingItem().id.id" 44 entity-id="vm.grid.operatingItem().id.id"
45 entity-type="{{vm.types.entityType.rule}}" 45 entity-type="{{vm.types.entityType.rule}}"
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 disable-attribute-scope-selection="true"> 48 disable-attribute-scope-selection="true">
49 </tb-attribute-table> 49 </tb-attribute-table>
50 </md-tab> 50 </md-tab>
51 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'rule.events' | translate }}"> 51 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" label="{{ 'rule.events' | translate }}">
52 <tb-event-table flex entity-type="vm.types.entityType.rule" 52 <tb-event-table flex entity-type="vm.types.entityType.rule"
53 entity-id="vm.grid.operatingItem().id.id" 53 entity-id="vm.grid.operatingItem().id.id"
54 tenant-id="vm.grid.operatingItem().tenantId.id" 54 tenant-id="vm.grid.operatingItem().tenantId.id"
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 disabled-event-types="{{vm.types.eventType.alarm.value}}"> 56 disabled-event-types="{{vm.types.eventType.alarm.value}}">
57 </tb-event-table> 57 </tb-event-table>
58 </md-tab> 58 </md-tab>
59 - <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" label="{{ 'relation.relations' | translate }}"> 59 + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" label="{{ 'relation.relations' | translate }}">
60 <tb-relation-table flex 60 <tb-relation-table flex
61 entity-id="vm.grid.operatingItem().id.id" 61 entity-id="vm.grid.operatingItem().id.id"
62 entity-type="{{vm.types.entityType.rule}}"> 62 entity-type="{{vm.types.entityType.rule}}">