Browse Source

Merge with master

pull/773/head
Igor Kulikov 8 years ago
parent
commit
016bbefaba
  1. 3
      application/build.gradle
  2. 4
      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. 2
      application/src/main/data/json/system/widget_bundles/cards.json
  7. 2
      application/src/main/data/upgrade/1.3.0/schema_update.cql
  8. 2
      application/src/main/data/upgrade/1.3.1/schema_update.sql
  9. 112
      application/src/main/data/upgrade/1.4.0/schema_update.cql
  10. 41
      application/src/main/data/upgrade/1.4.0/schema_update.sql
  11. 3
      application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java
  12. 2
      application/src/main/java/org/thingsboard/server/ThingsboardServerApplication.java
  13. 6
      application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
  14. 2
      application/src/main/java/org/thingsboard/server/actors/app/AppActor.java
  15. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActor.java
  16. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java
  17. 2
      application/src/main/java/org/thingsboard/server/actors/device/SessionInfo.java
  18. 2
      application/src/main/java/org/thingsboard/server/actors/device/ToDeviceRpcRequestMetadata.java
  19. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/PluginActor.java
  20. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/PluginActorMessageProcessor.java
  21. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/PluginCallbackMessage.java
  22. 80
      application/src/main/java/org/thingsboard/server/actors/plugin/PluginProcessingContext.java
  23. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/PluginTerminationMsg.java
  24. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/RuleToPluginMsgWrapper.java
  25. 5
      application/src/main/java/org/thingsboard/server/actors/plugin/SharedPluginProcessingContext.java
  26. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/TimeoutScheduler.java
  27. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/ValidationCallback.java
  28. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/ValidationResult.java
  29. 2
      application/src/main/java/org/thingsboard/server/actors/plugin/ValidationResultCode.java
  30. 4
      application/src/main/java/org/thingsboard/server/actors/rpc/BasicRpcSessionListener.java
  31. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcBroadcastMsg.java
  32. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcManagerActor.java
  33. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionActor.java
  34. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionClosedMsg.java
  35. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionConnectedMsg.java
  36. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionCreateRequestMsg.java
  37. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionDisconnectedMsg.java
  38. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/RpcSessionTellMsg.java
  39. 2
      application/src/main/java/org/thingsboard/server/actors/rpc/SessionActorInfo.java
  40. 2
      application/src/main/java/org/thingsboard/server/actors/rule/ChainProcessingContext.java
  41. 2
      application/src/main/java/org/thingsboard/server/actors/rule/ChainProcessingMetaData.java
  42. 2
      application/src/main/java/org/thingsboard/server/actors/rule/ComplexRuleActorChain.java
  43. 2
      application/src/main/java/org/thingsboard/server/actors/rule/CompoundRuleActorChain.java
  44. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleActor.java
  45. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleActorChain.java
  46. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleActorMessageProcessor.java
  47. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleActorMetaData.java
  48. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleContextAwareMsgProcessor.java
  49. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingContext.java
  50. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingMsg.java
  51. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleTerminationMsg.java
  52. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RuleToPluginTimeoutMsg.java
  53. 2
      application/src/main/java/org/thingsboard/server/actors/rule/RulesProcessedMsg.java
  54. 2
      application/src/main/java/org/thingsboard/server/actors/rule/SimpleRuleActorChain.java
  55. 2
      application/src/main/java/org/thingsboard/server/actors/service/ActorService.java
  56. 2
      application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java
  57. 2
      application/src/main/java/org/thingsboard/server/actors/service/ContextAwareActor.java
  58. 2
      application/src/main/java/org/thingsboard/server/actors/service/ContextBasedCreator.java
  59. 2
      application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java
  60. 2
      application/src/main/java/org/thingsboard/server/actors/service/RestMsgProcessor.java
  61. 2
      application/src/main/java/org/thingsboard/server/actors/service/WebSocketMsgProcessor.java
  62. 2
      application/src/main/java/org/thingsboard/server/actors/session/ASyncMsgProcessor.java
  63. 2
      application/src/main/java/org/thingsboard/server/actors/session/AbstractSessionActorMsgProcessor.java
  64. 2
      application/src/main/java/org/thingsboard/server/actors/session/SessionActor.java
  65. 2
      application/src/main/java/org/thingsboard/server/actors/session/SessionManagerActor.java
  66. 2
      application/src/main/java/org/thingsboard/server/actors/session/SessionTerminationMsg.java
  67. 2
      application/src/main/java/org/thingsboard/server/actors/session/SyncMsgProcessor.java
  68. 2
      application/src/main/java/org/thingsboard/server/actors/shared/AbstractContextAwareMsgProcessor.java
  69. 2
      application/src/main/java/org/thingsboard/server/actors/shared/ActorTerminationMsg.java
  70. 2
      application/src/main/java/org/thingsboard/server/actors/shared/ComponentMsgProcessor.java
  71. 2
      application/src/main/java/org/thingsboard/server/actors/shared/SessionTimeoutMsg.java
  72. 2
      application/src/main/java/org/thingsboard/server/actors/shared/plugin/PluginManager.java
  73. 2
      application/src/main/java/org/thingsboard/server/actors/shared/plugin/SystemPluginManager.java
  74. 2
      application/src/main/java/org/thingsboard/server/actors/shared/plugin/TenantPluginManager.java
  75. 2
      application/src/main/java/org/thingsboard/server/actors/shared/rule/RuleManager.java
  76. 2
      application/src/main/java/org/thingsboard/server/actors/shared/rule/SystemRuleManager.java
  77. 2
      application/src/main/java/org/thingsboard/server/actors/shared/rule/TenantRuleManager.java
  78. 2
      application/src/main/java/org/thingsboard/server/actors/stats/StatsActor.java
  79. 2
      application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistMsg.java
  80. 2
      application/src/main/java/org/thingsboard/server/actors/stats/StatsPersistTick.java
  81. 2
      application/src/main/java/org/thingsboard/server/actors/tenant/RuleChainDeviceMsg.java
  82. 2
      application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
  83. 43
      application/src/main/java/org/thingsboard/server/config/AuditLogLevelProperties.java
  84. 2
      application/src/main/java/org/thingsboard/server/config/JwtSettings.java
  85. 2
      application/src/main/java/org/thingsboard/server/config/MvcCorsProperties.java
  86. 2
      application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java
  87. 2
      application/src/main/java/org/thingsboard/server/config/ThingsboardMessageConfiguration.java
  88. 8
      application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
  89. 2
      application/src/main/java/org/thingsboard/server/config/WebConfig.java
  90. 2
      application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java
  91. 2
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  92. 2
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  93. 69
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  94. 114
      application/src/main/java/org/thingsboard/server/controller/AuditLogController.java
  95. 2
      application/src/main/java/org/thingsboard/server/controller/AuthController.java
  96. 42
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  97. 2
      application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java
  98. 29
      application/src/main/java/org/thingsboard/server/controller/CustomerController.java
  99. 280
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  100. 83
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java

3
application/build.gradle

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
*/
import org.apache.tools.ant.filters.ReplaceTokens
buildscript {

4
application/pom.xml

@ -1,6 +1,6 @@
<!--
Copyright © 2016-2017 The Thingsboard Authors
Copyright © 2016-2018 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>1.4.0-SNAPSHOT</version>
<version>1.4.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId>
</parent>
<groupId>org.thingsboard</groupId>

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

@ -1,6 +1,6 @@
<!--
Copyright © 2016-2017 The Thingsboard Authors
Copyright © 2016-2018 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-2017 The Thingsboard Authors
Copyright © 2016-2018 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-2017 The Thingsboard Authors
# Copyright © 2016-2018 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/json/system/widget_bundles/cards.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-2017 The Thingsboard Authors
-- Copyright © 2016-2018 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-2017 The Thingsboard Authors
-- Copyright © 2016-2018 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.

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

@ -0,0 +1,112 @@
--
-- Copyright © 2016-2018 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.
--
CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_entity_id (
tenant_id timeuuid,
id timeuuid,
customer_id timeuuid,
entity_id timeuuid,
entity_type text,
entity_name text,
user_id timeuuid,
user_name text,
action_type text,
action_data text,
action_status text,
action_failure_details text,
PRIMARY KEY ((tenant_id, entity_id, entity_type), id)
);
CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_customer_id (
tenant_id timeuuid,
id timeuuid,
customer_id timeuuid,
entity_id timeuuid,
entity_type text,
entity_name text,
user_id timeuuid,
user_name text,
action_type text,
action_data text,
action_status text,
action_failure_details text,
PRIMARY KEY ((tenant_id, customer_id), id)
);
CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_user_id (
tenant_id timeuuid,
id timeuuid,
customer_id timeuuid,
entity_id timeuuid,
entity_type text,
entity_name text,
user_id timeuuid,
user_name text,
action_type text,
action_data text,
action_status text,
action_failure_details text,
PRIMARY KEY ((tenant_id, user_id), id)
);
CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_tenant_id (
tenant_id timeuuid,
id timeuuid,
partition bigint,
customer_id timeuuid,
entity_id timeuuid,
entity_type text,
entity_name text,
user_id timeuuid,
user_name text,
action_type text,
action_data text,
action_status text,
action_failure_details text,
PRIMARY KEY ((tenant_id, partition), id)
);
CREATE TABLE IF NOT EXISTS thingsboard.audit_log_by_tenant_id_partitions (
tenant_id timeuuid,
partition bigint,
PRIMARY KEY (( tenant_id ), partition)
) WITH CLUSTERING ORDER BY ( partition ASC )
AND compaction = { 'class' : 'LeveledCompactionStrategy' };
DROP MATERIALIZED VIEW IF EXISTS thingsboard.dashboard_by_tenant_and_search_text;
DROP MATERIALIZED VIEW IF EXISTS thingsboard.dashboard_by_customer_and_search_text;
DROP TABLE IF EXISTS thingsboard.dashboard;
CREATE TABLE IF NOT EXISTS thingsboard.dashboard (
id timeuuid,
tenant_id timeuuid,
title text,
search_text text,
assigned_customers text,
configuration text,
PRIMARY KEY (id, tenant_id)
);
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.dashboard_by_tenant_and_search_text AS
SELECT *
from thingsboard.dashboard
WHERE tenant_id IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( tenant_id, search_text, id )
WITH CLUSTERING ORDER BY ( search_text ASC, id DESC );

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

@ -0,0 +1,41 @@
--
-- Copyright © 2016-2018 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.
--
CREATE TABLE IF NOT EXISTS audit_log (
id varchar(31) NOT NULL CONSTRAINT audit_log_pkey PRIMARY KEY,
tenant_id varchar(31),
customer_id varchar(31),
entity_id varchar(31),
entity_type varchar(255),
entity_name varchar(255),
user_id varchar(31),
user_name varchar(255),
action_type varchar(255),
action_data varchar(1000000),
action_status varchar(255),
action_failure_details varchar(1000000)
);
DROP TABLE IF EXISTS dashboard;
CREATE TABLE IF NOT EXISTS dashboard (
id varchar(31) NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY,
configuration varchar(10000000),
assigned_customers varchar(1000000),
search_text varchar(255),
tenant_id varchar(31),
title varchar(255)
);

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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;
import lombok.extern.slf4j.Slf4j;

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -40,6 +40,7 @@ import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
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.audit.AuditLogService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.event.EventService;
@ -113,6 +114,9 @@ public class ActorSystemContext {
@Autowired
@Getter private RelationService relationService;
@Autowired
@Getter private AuditLogService auditLogService;
@Autowired
@Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint;

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/DeviceActorMessageProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/PluginActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/PluginActorMessageProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/PluginCallbackMessage.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.

80
application/src/main/java/org/thingsboard/server/actors/plugin/PluginProcessingContext.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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,6 +26,7 @@ import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.*;
import org.thingsboard.server.common.data.kv.AttributeKey;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@ -41,9 +42,7 @@ import org.thingsboard.server.extensions.api.device.DeviceAttributesEventNotific
import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext;
import org.thingsboard.server.extensions.api.plugins.PluginCallback;
import org.thingsboard.server.extensions.api.plugins.PluginContext;
import org.thingsboard.server.extensions.api.plugins.msg.PluginToRuleMsg;
import org.thingsboard.server.extensions.api.plugins.msg.TimeoutMsg;
import org.thingsboard.server.extensions.api.plugins.msg.ToDeviceRpcRequest;
import org.thingsboard.server.extensions.api.plugins.msg.*;
import org.thingsboard.server.extensions.api.plugins.rpc.PluginRpcMsg;
import org.thingsboard.server.extensions.api.plugins.rpc.RpcMsg;
import org.thingsboard.server.extensions.api.plugins.ws.PluginWebsocketSessionRef;
@ -196,6 +195,52 @@ public final class PluginProcessingContext implements PluginContext {
}));
}
@Override
public void logAttributesUpdated(PluginApiCallSecurityContext ctx, EntityId entityId, String attributeType,
List<AttributeKvEntry> attributes, Exception e) {
pluginCtx.auditLogService.logEntityAction(
ctx.getTenantId(),
ctx.getCustomerId(),
ctx.getUserId(),
ctx.getUserName(),
(UUIDBased & EntityId)entityId,
null,
ActionType.ATTRIBUTES_UPDATED,
e,
attributeType,
attributes);
}
@Override
public void logAttributesDeleted(PluginApiCallSecurityContext ctx, EntityId entityId, String attributeType, List<String> keys, Exception e) {
pluginCtx.auditLogService.logEntityAction(
ctx.getTenantId(),
ctx.getCustomerId(),
ctx.getUserId(),
ctx.getUserName(),
(UUIDBased & EntityId)entityId,
null,
ActionType.ATTRIBUTES_DELETED,
e,
attributeType,
keys);
}
@Override
public void logAttributesRead(PluginApiCallSecurityContext ctx, EntityId entityId, String attributeType, List<String> keys, Exception e) {
pluginCtx.auditLogService.logEntityAction(
ctx.getTenantId(),
ctx.getCustomerId(),
ctx.getUserId(),
ctx.getUserName(),
(UUIDBased & EntityId)entityId,
null,
ActionType.ATTRIBUTES_READ,
e,
attributeType,
keys);
}
@Override
public void loadLatestTimeseries(final EntityId entityId, final Collection<String> keys, final PluginCallback<List<TsKvEntry>> callback) {
validate(entityId, new ValidationCallback(callback, ctx -> {
@ -429,12 +474,12 @@ public final class PluginProcessingContext implements PluginContext {
@Override
public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) {
return this.pluginCtx.relationService.findByFromAndType(from, relationType, RelationTypeGroup.COMMON);
return this.pluginCtx.relationService.findByFromAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
}
@Override
public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) {
return this.pluginCtx.relationService.findByToAndType(from, relationType, RelationTypeGroup.COMMON);
return this.pluginCtx.relationService.findByToAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
}
@Override
@ -460,6 +505,29 @@ public final class PluginProcessingContext implements PluginContext {
pluginCtx.sendRpcRequest(msg);
}
@Override
public void logRpcRequest(PluginApiCallSecurityContext ctx, DeviceId deviceId, ToDeviceRpcRequestBody body, boolean oneWay, Optional<RpcError> rpcError, Exception e) {
String rpcErrorStr = "";
if (rpcError.isPresent()) {
rpcErrorStr = "RPC Error: " + rpcError.get().name();
}
String method = body.getMethod();
String params = body.getParams();
pluginCtx.auditLogService.logEntityAction(
ctx.getTenantId(),
ctx.getCustomerId(),
ctx.getUserId(),
ctx.getUserName(),
deviceId,
null,
ActionType.RPC_CALL,
e,
rpcErrorStr,
new Boolean(oneWay),
method,
params);
}
@Override
public void scheduleTimeoutMsg(TimeoutMsg msg) {
pluginCtx.scheduleTimeoutMsg(msg);

2
application/src/main/java/org/thingsboard/server/actors/plugin/PluginTerminationMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/RuleToPluginMsgWrapper.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/actors/plugin/SharedPluginProcessingContext.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -27,6 +27,7 @@ import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
import org.thingsboard.server.common.data.id.PluginId;
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.device.DeviceService;
import org.thingsboard.server.dao.plugin.PluginService;
@ -63,6 +64,7 @@ public final class SharedPluginProcessingContext {
final ClusterRpcService rpcService;
final ClusterRoutingService routingService;
final RelationService relationService;
final AuditLogService auditLogService;
final PluginId pluginId;
final TenantId tenantId;
@ -86,6 +88,7 @@ public final class SharedPluginProcessingContext {
this.customerService = sysContext.getCustomerService();
this.tenantService = sysContext.getTenantService();
this.relationService = sysContext.getRelationService();
this.auditLogService = sysContext.getAuditLogService();
}
public PluginId getPluginId() {

2
application/src/main/java/org/thingsboard/server/actors/plugin/TimeoutScheduler.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/ValidationCallback.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/ValidationResult.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/ValidationResultCode.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rpc/BasicRpcSessionListener.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -148,7 +148,7 @@ public class BasicRpcSessionListener implements GrpcSessionListener {
DeviceId deviceId = new DeviceId(toUUID(msg.getDeviceId()));
ToDeviceRpcRequestBody requestBody = new ToDeviceRpcRequestBody(msg.getMethod(), msg.getParams());
ToDeviceRpcRequest request = new ToDeviceRpcRequest(toUUID(msg.getMsgId()), deviceTenantId, deviceId, msg.getOneway(), msg.getExpTime(), requestBody);
ToDeviceRpcRequest request = new ToDeviceRpcRequest(toUUID(msg.getMsgId()), null, deviceTenantId, deviceId, msg.getOneway(), msg.getExpTime(), requestBody);
return new ToDeviceRpcRequestPluginMsg(serverAddress, pluginId, pluginTenantId, request);
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/ChainProcessingContext.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/ChainProcessingMetaData.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/ComplexRuleActorChain.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/CompoundRuleActorChain.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleActorChain.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleActorMessageProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleActorMetaData.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleContextAwareMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleProcessingContext.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleProcessingMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleTerminationMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleToPluginTimeoutMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RulesProcessedMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/SimpleRuleActorChain.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/ComponentActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/ContextAwareActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/DefaultActorService.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/RestMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/WebSocketMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/session/ASyncMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/session/AbstractSessionActorMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/session/SessionActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/session/SessionManagerActor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/session/SessionTerminationMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/session/SyncMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/AbstractContextAwareMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/ComponentMsgProcessor.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/SessionTimeoutMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/PluginManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/SystemPluginManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/plugin/TenantPluginManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/RuleManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/SystemRuleManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/rule/TenantRuleManager.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/RuleChainDeviceMsg.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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
application/src/main/java/org/thingsboard/server/config/AuditLogLevelProperties.java

@ -0,0 +1,43 @@
/**
* Copyright © 2016-2018 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.
*/
package org.thingsboard.server.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionType;
import java.util.HashMap;
import java.util.Map;
@Configuration
@ConfigurationProperties(prefix = "audit_log.logging_level")
public class AuditLogLevelProperties {
private Map<String, String> mask = new HashMap<>();
public AuditLogLevelProperties() {
super();
}
public void setMask(Map<String, String> mask) {
this.mask = mask;
}
public Map<String, String> getMask() {
return this.mask;
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/SwaggerConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/ThingsboardMessageConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -40,6 +40,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.thingsboard.server.dao.audit.AuditLogLevelFilter;
import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
import org.thingsboard.server.service.security.auth.rest.RestAuthenticationProvider;
import org.thingsboard.server.service.security.auth.rest.RestLoginProcessingFilter;
@ -198,4 +199,9 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
return new CorsFilter(source);
}
}
@Bean
public AuditLogLevelFilter auditLogLevelFilter(@Autowired AuditLogLevelProperties auditLogLevelProperties) {
return new AuditLogLevelFilter(auditLogLevelProperties.getMask());
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/WebSocketConfiguration.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/AdminController.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/AlarmController.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -21,7 +21,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@ -73,8 +75,16 @@ public class AssetController extends BaseController {
checkCustomerId(asset.getCustomerId());
}
}
return checkNotNull(assetService.saveAsset(asset));
Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
logEntityAction(savedAsset.getId(), savedAsset,
savedAsset.getCustomerId(),
asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
return savedAsset;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), asset,
null, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e);
}
}
@ -86,9 +96,18 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
checkAssetId(assetId);
Asset asset = checkAssetId(assetId);
assetService.deleteAsset(assetId);
logEntityAction(assetId, asset,
asset.getCustomerId(),
ActionType.DELETED, null, strAssetId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET),
null,
null,
ActionType.DELETED, e, strAssetId);
throw handleException(e);
}
}
@ -102,13 +121,24 @@ public class AssetController extends BaseController {
checkParameter(ASSET_ID, strAssetId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId);
AssetId assetId = new AssetId(toUUID(strAssetId));
checkAssetId(assetId);
return checkNotNull(assetService.assignAssetToCustomer(assetId, customerId));
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(assetId, customerId));
logEntityAction(assetId, savedAsset,
savedAsset.getCustomerId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, strCustomerId, customer.getName());
return savedAsset;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId, strCustomerId);
throw handleException(e);
}
}
@ -124,8 +154,22 @@ public class AssetController extends BaseController {
if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
throw new IncorrectParameterException("Asset isn't assigned to any customer!");
}
return checkNotNull(assetService.unassignAssetFromCustomer(assetId));
Customer customer = checkCustomerId(asset.getCustomerId());
Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(assetId));
logEntityAction(assetId, asset,
asset.getCustomerId(),
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strAssetId, customer.getId().toString(), customer.getName());
return savedAsset;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), null,
null,
ActionType.UNASSIGNED_FROM_CUSTOMER, e, strAssetId);
throw handleException(e);
}
}
@ -139,8 +183,19 @@ public class AssetController extends BaseController {
AssetId assetId = new AssetId(toUUID(strAssetId));
Asset asset = checkAssetId(assetId);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(asset.getTenantId());
return checkNotNull(assetService.assignAssetToCustomer(assetId, publicCustomer.getId()));
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(assetId, publicCustomer.getId()));
logEntityAction(assetId, savedAsset,
savedAsset.getCustomerId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, publicCustomer.getId().toString(), publicCustomer.getName());
return savedAsset;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId);
throw handleException(e);
}
}

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

@ -0,0 +1,114 @@
/**
* Copyright © 2016-2018 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.
*/
package org.thingsboard.server.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.audit.AuditLog;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.exception.ThingsboardException;
import java.util.UUID;
@RestController
@RequestMapping("/api")
public class AuditLogController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public TimePageData<AuditLog> getAuditLogsByCustomerId(
@PathVariable("customerId") String strCustomerId,
@RequestParam int limit,
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
try {
checkParameter("CustomerId", strCustomerId);
TenantId tenantId = getCurrentUser().getTenantId();
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(auditLogService.findAuditLogsByTenantIdAndCustomerId(tenantId, new CustomerId(UUID.fromString(strCustomerId)), pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs/user/{userId}", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public TimePageData<AuditLog> getAuditLogsByUserId(
@PathVariable("userId") String strUserId,
@RequestParam int limit,
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
try {
checkParameter("UserId", strUserId);
TenantId tenantId = getCurrentUser().getTenantId();
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(auditLogService.findAuditLogsByTenantIdAndUserId(tenantId, new UserId(UUID.fromString(strUserId)), pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public TimePageData<AuditLog> getAuditLogsByEntityId(
@PathVariable("entityType") String strEntityType,
@PathVariable("entityId") String strEntityId,
@RequestParam int limit,
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
try {
checkParameter("EntityId", strEntityId);
checkParameter("EntityType", strEntityType);
TenantId tenantId = getCurrentUser().getTenantId();
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(auditLogService.findAuditLogsByTenantIdAndEntityId(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public TimePageData<AuditLog> getAuditLogs(
@RequestParam int limit,
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(auditLogService.findAuditLogsByTenantId(tenantId, pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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,9 +15,12 @@
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ -27,6 +30,8 @@ import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmId;
import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionStatus;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.*;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
@ -39,6 +44,7 @@ import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetService;
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.DeviceCredentialsService;
@ -72,6 +78,7 @@ public abstract class BaseController {
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!";
@Autowired
private ThingsboardErrorResponseHandler errorResponseHandler;
@ -117,6 +124,8 @@ public abstract class BaseController {
@Autowired
protected RelationService relationService;
@Autowired
protected AuditLogService auditLogService;
@ExceptionHandler(ThingsboardException.class)
public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {
@ -129,7 +138,7 @@ public abstract class BaseController {
private ThingsboardException handleException(Exception exception, boolean logException) {
if (logException) {
log.error("Error [{}]", exception.getMessage());
log.error("Error [{}]", exception.getMessage(), exception);
}
String cause = "";
@ -414,7 +423,7 @@ public abstract class BaseController {
try {
validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
Dashboard dashboard = dashboardService.findDashboardById(dashboardId);
checkDashboard(dashboard, true);
checkDashboard(dashboard);
return dashboard;
} catch (Exception e) {
throw handleException(e, false);
@ -425,28 +434,23 @@ public abstract class BaseController {
try {
validateId(dashboardId, "Incorrect dashboardId " + dashboardId);
DashboardInfo dashboardInfo = dashboardService.findDashboardInfoById(dashboardId);
SecurityUser authUser = getCurrentUser();
checkDashboard(dashboardInfo, authUser.getAuthority() != Authority.SYS_ADMIN);
checkDashboard(dashboardInfo);
return dashboardInfo;
} catch (Exception e) {
throw handleException(e, false);
}
}
private void checkDashboard(DashboardInfo dashboard, boolean checkCustomerId) throws ThingsboardException {
private void checkDashboard(DashboardInfo dashboard) throws ThingsboardException {
checkNotNull(dashboard);
checkTenantId(dashboard.getTenantId());
SecurityUser authUser = getCurrentUser();
if (authUser.getAuthority() == Authority.CUSTOMER_USER) {
if (dashboard.getCustomerId() == null || dashboard.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
if (!dashboard.isAssignedToCustomer(authUser.getCustomerId())) {
throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
ThingsboardErrorCode.PERMISSION_DENIED);
}
}
if (checkCustomerId &&
dashboard.getCustomerId() != null && !dashboard.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
checkCustomerId(dashboard.getCustomerId());
}
}
ComponentDescriptor checkComponentDescriptorByClazz(String clazz) throws ThingsboardException {
@ -541,4 +545,20 @@ public abstract class BaseController {
serverPort);
return baseUrl;
}
protected <I extends UUIDBased & EntityId> I emptyId(EntityType entityType) {
return (I)EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID);
}
protected <E extends BaseData<I> & HasName,
I extends UUIDBased & EntityId> void logEntityAction(I entityId, E entity, CustomerId customerId,
ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException {
User user = getCurrentUser();
if (customerId == null || customerId.isNullUid()) {
customerId = user.getCustomerId();
}
auditLogService.logEntityAction(user.getTenantId(), customerId, user.getId(), user.getName(), entityId, entity, actionType, e, additionalInfo);
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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/controller/CustomerController.java

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -22,6 +22,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageData;
@ -86,8 +88,18 @@ public class CustomerController extends BaseController {
public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException {
try {
customer.setTenantId(getCurrentUser().getTenantId());
return checkNotNull(customerService.saveCustomer(customer));
Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer));
logEntityAction(savedCustomer.getId(), savedCustomer,
savedCustomer.getId(),
customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
return savedCustomer;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.CUSTOMER), customer,
null, customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e);
}
}
@ -99,9 +111,20 @@ public class CustomerController extends BaseController {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId);
customerService.deleteCustomer(customerId);
logEntityAction(customerId, customer,
customer.getId(),
ActionType.DELETED, null, strCustomerId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.CUSTOMER),
null,
null,
ActionType.DELETED, e, strCustomerId);
throw handleException(e);
}
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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,18 +18,22 @@ package org.thingsboard.server.controller;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.*;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
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.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.exception.ThingsboardException;
import java.util.HashSet;
import java.util.Set;
@RestController
@RequestMapping("/api")
public class DashboardController extends BaseController {
@ -75,8 +79,17 @@ public class DashboardController extends BaseController {
public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException {
try {
dashboard.setTenantId(getCurrentUser().getTenantId());
return checkNotNull(dashboardService.saveDashboard(dashboard));
Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard));
logEntityAction(savedDashboard.getId(), savedDashboard,
null,
dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
return savedDashboard;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), dashboard,
null, dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e);
}
}
@ -88,9 +101,20 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
checkDashboardId(dashboardId);
Dashboard dashboard = checkDashboardId(dashboardId);
dashboardService.deleteDashboard(dashboardId);
logEntityAction(dashboardId, dashboard,
null,
ActionType.DELETED, null, strDashboardId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD),
null,
null,
ActionType.DELETED, e, strDashboardId);
throw handleException(e);
}
}
@ -104,30 +128,207 @@ public class DashboardController extends BaseController {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId);
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
checkDashboardId(dashboardId);
return checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
logEntityAction(dashboardId, savedDashboard,
customerId,
ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, strCustomerId, customer.getName());
return savedDashboard;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId, strCustomerId);
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody
public Dashboard unassignDashboardFromCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public Dashboard unassignDashboardFromCustomer(@PathVariable("customerId") String strCustomerId,
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
checkParameter(DASHBOARD_ID, strDashboardId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId);
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
logEntityAction(dashboardId, dashboard,
customerId,
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customer.getId().toString(), customer.getName());
return savedDashboard;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST)
@ResponseBody
public Dashboard updateDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
@RequestBody String[] strCustomerIds) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Set<CustomerId> customerIds = new HashSet<>();
if (strCustomerIds != null) {
for (String strCustomerId : strCustomerIds) {
customerIds.add(new CustomerId(toUUID(strCustomerId)));
}
}
Set<CustomerId> addedCustomerIds = new HashSet<>();
Set<CustomerId> removedCustomerIds = new HashSet<>();
for (CustomerId customerId : customerIds) {
if (!dashboard.isAssignedToCustomer(customerId)) {
addedCustomerIds.add(customerId);
}
}
Set<ShortCustomerInfo> assignedCustomers = dashboard.getAssignedCustomers();
if (assignedCustomers != null) {
for (ShortCustomerInfo customerInfo : assignedCustomers) {
if (!customerIds.contains(customerInfo.getCustomerId())) {
removedCustomerIds.add(customerInfo.getCustomerId());
}
}
}
if (addedCustomerIds.isEmpty() && removedCustomerIds.isEmpty()) {
return dashboard;
} else {
Dashboard savedDashboard = null;
for (CustomerId customerId : addedCustomerIds) {
savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
logEntityAction(dashboardId, savedDashboard,
customerId,
ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
}
for (CustomerId customerId : removedCustomerIds) {
ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
logEntityAction(dashboardId, dashboard,
customerId,
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
}
return savedDashboard;
}
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST)
@ResponseBody
public Dashboard addDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
@RequestBody String[] strCustomerIds) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Set<CustomerId> customerIds = new HashSet<>();
if (strCustomerIds != null) {
for (String strCustomerId : strCustomerIds) {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
if (!dashboard.isAssignedToCustomer(customerId)) {
customerIds.add(customerId);
}
}
}
if (customerIds.isEmpty()) {
return dashboard;
} else {
Dashboard savedDashboard = null;
for (CustomerId customerId : customerIds) {
savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, customerId));
ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
logEntityAction(dashboardId, savedDashboard,
customerId,
ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
}
return savedDashboard;
}
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST)
@ResponseBody
public Dashboard removeDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
@RequestBody String[] strCustomerIds) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
if (dashboard.getCustomerId() == null || dashboard.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
throw new IncorrectParameterException("Dashboard isn't assigned to any customer!");
Set<CustomerId> customerIds = new HashSet<>();
if (strCustomerIds != null) {
for (String strCustomerId : strCustomerIds) {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
if (dashboard.isAssignedToCustomer(customerId)) {
customerIds.add(customerId);
}
}
}
if (customerIds.isEmpty()) {
return dashboard;
} else {
Dashboard savedDashboard = null;
for (CustomerId customerId : customerIds) {
ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, customerId));
logEntityAction(dashboardId, dashboard,
customerId,
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, customerId.toString(), customerInfo.getTitle());
}
return savedDashboard;
}
return checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId));
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
throw handleException(e);
}
}
@ -141,8 +342,46 @@ public class DashboardController extends BaseController {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId());
return checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, publicCustomer.getId()));
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(dashboardId, publicCustomer.getId()));
logEntityAction(dashboardId, savedDashboard,
publicCustomer.getId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strDashboardId, publicCustomer.getId().toString(), publicCustomer.getName());
return savedDashboard;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strDashboardId);
throw handleException(e);
}
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody
public Dashboard unassignDashboardFromPublicCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
Dashboard dashboard = checkDashboardId(dashboardId);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId());
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(dashboardId, publicCustomer.getId()));
logEntityAction(dashboardId, dashboard,
publicCustomer.getId(),
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDashboardId, publicCustomer.getId().toString(), publicCustomer.getName());
return savedDashboard;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD), null,
null,
ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDashboardId);
throw handleException(e);
}
}
@ -186,19 +425,20 @@ public class DashboardController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/dashboards", params = { "limit" }, method = RequestMethod.GET)
@ResponseBody
public TextPageData<DashboardInfo> getCustomerDashboards(
public TimePageData<DashboardInfo> getCustomerDashboards(
@PathVariable("customerId") String strCustomerId,
@RequestParam int limit,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String idOffset,
@RequestParam(required = false) String textOffset) throws ThingsboardException {
@RequestParam(required = false) Long startTime,
@RequestParam(required = false) Long endTime,
@RequestParam(required = false, defaultValue = "false") boolean ascOrder,
@RequestParam(required = false) String offset) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
try {
TenantId tenantId = getCurrentUser().getTenantId();
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset);
return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink).get());
} catch (Exception e) {
throw handleException(e);
}

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

@ -1,5 +1,5 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
* Copyright © 2016-2018 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.
@ -22,6 +22,10 @@ import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionStatus;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -29,7 +33,6 @@ import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.exception.ThingsboardErrorCode;
@ -75,14 +78,22 @@ public class DeviceController extends BaseController {
}
}
Device savedDevice = checkNotNull(deviceService.saveDevice(device));
actorService
.onDeviceNameOrTypeUpdate(
savedDevice.getTenantId(),
savedDevice.getId(),
savedDevice.getName(),
savedDevice.getType());
logEntityAction(savedDevice.getId(), savedDevice,
savedDevice.getCustomerId(),
device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
return savedDevice;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), device,
null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e);
}
}
@ -94,9 +105,18 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
checkDeviceId(deviceId);
Device device = checkDeviceId(deviceId);
deviceService.deleteDevice(deviceId);
logEntityAction(deviceId, device,
device.getCustomerId(),
ActionType.DELETED, null, strDeviceId);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE),
null,
null,
ActionType.DELETED, e, strDeviceId);
throw handleException(e);
}
}
@ -110,13 +130,22 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId);
Customer customer = checkCustomerId(customerId);
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
checkDeviceId(deviceId);
return checkNotNull(deviceService.assignDeviceToCustomer(deviceId, customerId));
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(deviceId, customerId));
logEntityAction(deviceId, savedDevice,
savedDevice.getCustomerId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, strCustomerId, customer.getName());
return savedDevice;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId, strCustomerId);
throw handleException(e);
}
}
@ -132,8 +161,19 @@ public class DeviceController extends BaseController {
if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
throw new IncorrectParameterException("Device isn't assigned to any customer!");
}
return checkNotNull(deviceService.unassignDeviceFromCustomer(deviceId));
Customer customer = checkCustomerId(device.getCustomerId());
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(deviceId));
logEntityAction(deviceId, device,
device.getCustomerId(),
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDeviceId, customer.getId().toString(), customer.getName());
return savedDevice;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null,
null,
ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDeviceId);
throw handleException(e);
}
}
@ -147,8 +187,17 @@ public class DeviceController extends BaseController {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
Device device = checkDeviceId(deviceId);
Customer publicCustomer = customerService.findOrCreatePublicCustomer(device.getTenantId());
return checkNotNull(deviceService.assignDeviceToCustomer(deviceId, publicCustomer.getId()));
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(deviceId, publicCustomer.getId()));
logEntityAction(deviceId, savedDevice,
savedDevice.getCustomerId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, publicCustomer.getId().toString(), publicCustomer.getName());
return savedDevice;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null,
null,
ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId);
throw handleException(e);
}
}
@ -160,9 +209,16 @@ public class DeviceController extends BaseController {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
checkDeviceId(deviceId);
return checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(deviceId));
Device device = checkDeviceId(deviceId);
DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(deviceId));
logEntityAction(deviceId, device,
device.getCustomerId(),
ActionType.CREDENTIALS_READ, null, strDeviceId);
return deviceCredentials;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null,
null,
ActionType.CREDENTIALS_READ, e, strDeviceId);
throw handleException(e);
}
}
@ -173,11 +229,17 @@ public class DeviceController extends BaseController {
public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException {
checkNotNull(deviceCredentials);
try {
checkDeviceId(deviceCredentials.getDeviceId());
Device device = checkDeviceId(deviceCredentials.getDeviceId());
DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(deviceCredentials));
actorService.onCredentialsUpdate(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId());
logEntityAction(device.getId(), device,
device.getCustomerId(),
ActionType.CREDENTIALS_UPDATED, null, deviceCredentials);
return result;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DEVICE), null,
null,
ActionType.CREDENTIALS_UPDATED, e, deviceCredentials);
throw handleException(e);
}
}
@ -306,5 +368,4 @@ public class DeviceController extends BaseController {
throw handleException(e);
}
}
}

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

Loading…
Cancel
Save