From 305005490f1e7083006461aed5f1a74188b6e277 Mon Sep 17 00:00:00 2001 From: vparomskiy Date: Thu, 12 Apr 2018 10:57:48 +0300 Subject: [PATCH] move exception to api move MailService to RuleEngine implement MsgToEmil Transformer and SendEmail Node --- .../server/actors/ActorSystemContext.java | 13 +- .../actors/ruleChain/DefaultTbContext.java | 15 +- .../ThingsboardSecurityConfiguration.java | 2 - .../server/config/WebSocketConfiguration.java | 4 +- .../server/controller/AdminController.java | 4 +- .../server/controller/AlarmController.java | 4 +- .../server/controller/AssetController.java | 4 +- .../server/controller/AuditLogController.java | 2 +- .../server/controller/AuthController.java | 6 +- .../server/controller/BaseController.java | 8 +- .../ComponentDescriptorController.java | 2 +- .../server/controller/CustomerController.java | 2 +- .../controller/DashboardController.java | 4 +- .../server/controller/DeviceController.java | 5 +- .../controller/EntityRelationController.java | 4 +- .../server/controller/EventController.java | 4 +- .../server/controller/PluginController.java | 2 +- .../controller/RuleChainController.java | 4 +- .../server/controller/RuleController.java | 2 +- .../controller/TelemetryController.java | 2 +- .../server/controller/TenantController.java | 2 +- .../server/controller/UserController.java | 6 +- .../controller/WidgetTypeController.java | 2 +- .../controller/WidgetsBundleController.java | 2 +- .../plugin/PluginApiController.java | 21 --- .../exception/ThingsboardErrorResponse.java | 1 + .../ThingsboardErrorResponseHandler.java | 4 +- .../service/mail/DefaultMailService.java | 100 +++++++----- .../service/mail/MailExecutorService.java | 54 +++++++ .../service/security/AccessValidator.java | 2 +- .../src/main/resources/thingsboard.yml | 1 + .../server/service/mail/TestMailService.java | 3 +- .../service/script/NashornJsEngineTest.java | 151 ++++++++++++++++++ .../thingsboard/server/common/data/User.java | 4 + .../data}/exception/ThingsboardErrorCode.java | 2 +- .../data}/exception/ThingsboardException.java | 2 +- .../server/common/msg/TbMsgMetaData.java | 4 + .../rule/engine/api}/MailService.java | 10 +- .../rule/engine/api/TbContext.java | 4 + rule-engine/rule-engine-components/pom.xml | 10 ++ .../rule/engine/mail/EmailPojo.java | 32 ++++ .../rule/engine/mail/RuleVelocityUtils.java | 68 ++++++++ .../rule/engine/mail/TbMsgToEmailNode.java | 114 +++++++++++++ .../mail/TbMsgToEmailNodeConfiguration.java | 41 +++++ .../rule/engine/mail/TbSendEmailNode.java | 89 +++++++++++ .../mail/TbSendEmailNodeConfiguration.java | 32 ++++ .../engine/metadata/TbGetAttributesNode.java | 8 +- .../engine/filter/TbJsFilterNodeTest.java | 85 +++------- .../engine/filter/TbJsSwitchNodeTest.java | 54 ++----- .../engine/mail/TbMsgToEmailNodeTest.java | 98 ++++++++++++ .../transform/TbTransformMsgNodeTest.java | 57 +++---- 51 files changed, 895 insertions(+), 261 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java create mode 100644 application/src/test/java/org/thingsboard/server/service/script/NashornJsEngineTest.java rename {application/src/main/java/org/thingsboard/server => common/data/src/main/java/org/thingsboard/server/common/data}/exception/ThingsboardErrorCode.java (95%) rename {application/src/main/java/org/thingsboard/server => common/data/src/main/java/org/thingsboard/server/common/data}/exception/ThingsboardException.java (96%) rename {application/src/main/java/org/thingsboard/server/service/mail => rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api}/MailService.java (80%) create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/EmailPojo.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/RuleVelocityUtils.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeConfiguration.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNodeConfiguration.java create mode 100644 rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeTest.java diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index b2496c0875..7c7747cec3 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.rule.engine.api.ListeningExecutor; +import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.actors.service.ActorService; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Event; @@ -58,6 +59,8 @@ import org.thingsboard.server.service.cluster.discovery.DiscoveryService; import org.thingsboard.server.service.cluster.routing.ClusterRoutingService; import org.thingsboard.server.service.cluster.rpc.ClusterRpcService; import org.thingsboard.server.service.component.ComponentDiscoveryService; +import org.thingsboard.server.service.mail.MailExecutorService; +import org.thingsboard.server.service.script.JsExecutorService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import java.io.IOException; @@ -164,7 +167,15 @@ public class ActorSystemContext { @Autowired @Getter - private ListeningExecutor jsExecutor; + private JsExecutorService jsExecutor; + + @Autowired + @Getter + private MailExecutorService mailExecutor; + + @Autowired + @Getter + private MailService mailService; @Value("${actors.session.sync.timeout}") @Getter diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index 9b6e4ba954..4ff75bf2a3 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -18,10 +18,7 @@ package org.thingsboard.server.actors.ruleChain; import akka.actor.ActorRef; import akka.actor.Cancellable; import com.google.common.base.Function; -import org.thingsboard.rule.engine.api.ListeningExecutor; -import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; -import org.thingsboard.rule.engine.api.ScriptEngine; -import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.*; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.TenantId; @@ -135,6 +132,11 @@ class DefaultTbContext implements TbContext { return mainCtx.getJsExecutor(); } + @Override + public ListeningExecutor getMailExecutor() { + return mainCtx.getMailExecutor(); + } + @Override public ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames) { return new NashornJsEngine(script, functionName, argNames); @@ -194,4 +196,9 @@ class DefaultTbContext implements TbContext { public RelationService getRelationService() { return mainCtx.getRelationService(); } + + @Override + public MailService getMailService() { + return mainCtx.getMailService(); + } } diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 2952529812..24c533c59d 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -37,7 +36,6 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 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; diff --git a/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java b/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java index d44c50e9cd..2e5050a9ad 100644 --- a/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/WebSocketConfiguration.java @@ -17,8 +17,8 @@ package org.thingsboard.server.config; import java.util.Map; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.controller.plugin.TbWebSocketHandler; import org.thingsboard.server.service.security.model.SecurityUser; import org.springframework.context.annotation.Bean; diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index e9a6ba3816..5a43125bbf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -20,8 +20,8 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.dao.settings.AdminSettingsService; -import org.thingsboard.server.exception.ThingsboardException; -import org.thingsboard.server.service.mail.MailService; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.service.update.UpdateService; import org.thingsboard.server.service.update.model.UpdateMessage; diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 1959f4e528..81bcf7e765 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -23,8 +23,8 @@ import org.thingsboard.server.common.data.alarm.*; import org.thingsboard.server.common.data.id.*; import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; @RestController @RequestMapping("/api") diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 9b439133d3..0e348f997e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -33,8 +33,8 @@ import org.thingsboard.server.common.data.asset.AssetSearchQuery; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.service.security.model.SecurityUser; import java.util.ArrayList; diff --git a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java index 75bcf2ab15..e8685c74f9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java @@ -24,7 +24,7 @@ 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 org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index ef38d802ec..96ff5162c7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -28,9 +28,9 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.bind.annotation.*; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.security.UserCredentials; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; -import org.thingsboard.server.service.mail.MailService; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.UserPrincipal; diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 3294d5fc59..c7574e86ba 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -15,12 +15,9 @@ */ 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; @@ -30,7 +27,6 @@ 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; @@ -61,9 +57,9 @@ import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetsBundleService; -import org.thingsboard.server.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.service.component.ComponentDiscoveryService; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java index 7a43cd35a2..6313d615a3 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java @@ -19,7 +19,7 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentType; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.HashSet; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index b16470216a..7763f3c00a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; @RestController @RequestMapping("/api") diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index d2952a16cb..4ec2bbab05 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -27,9 +27,7 @@ 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 org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.HashSet; import java.util.Set; diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index bceea54135..1f4b02a88b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -23,7 +23,6 @@ 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; @@ -35,8 +34,8 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.service.security.model.SecurityUser; import java.util.ArrayList; diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java index 03054df985..3a3b78b52f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java @@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationInfo; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.EntityRelationsQuery; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/EventController.java b/application/src/main/java/org/thingsboard/server/controller/EventController.java index 331b15eb09..f67f113144 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EventController.java @@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; @RestController @RequestMapping("/api") diff --git a/application/src/main/java/org/thingsboard/server/controller/PluginController.java b/application/src/main/java/org/thingsboard/server/controller/PluginController.java index ed1760057b..3bc385d7b2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/PluginController.java +++ b/application/src/main/java/org/thingsboard/server/controller/PluginController.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.PluginMetaData; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index f69ad819ba..f20ff8f915 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -28,20 +28,18 @@ import org.springframework.web.bind.annotation.*; import org.thingsboard.rule.engine.api.ScriptEngine; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.id.PluginId; import org.thingsboard.server.common.data.id.RuleChainId; 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.plugin.ComponentLifecycleEvent; -import org.thingsboard.server.common.data.plugin.PluginMetaData; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.service.script.NashornJsEngine; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleController.java b/application/src/main/java/org/thingsboard/server/controller/RuleController.java index 9a269029b5..4528d814a5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleController.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.PluginMetaData; import org.thingsboard.server.common.data.rule.RuleMetaData; import org.thingsboard.server.common.data.security.Authority; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 6ff8287b29..80ddc2ba32 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -58,7 +58,7 @@ import org.thingsboard.server.common.msg.core.TelemetryUploadRequest; import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.timeseries.TimeseriesService; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.extensions.api.exception.InvalidParametersException; import org.thingsboard.server.extensions.api.exception.UncheckedApiException; import org.thingsboard.server.extensions.api.plugins.PluginConstants; diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantController.java b/application/src/main/java/org/thingsboard/server/controller/TenantController.java index 5acb4eb216..bf49074f91 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantController.java @@ -24,7 +24,7 @@ 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.dao.tenant.TenantService; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; @RestController @RequestMapping("/api") diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 2a1531ac99..52b207db74 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -29,9 +29,9 @@ 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.UserCredentials; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; -import org.thingsboard.server.service.mail.MailService; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.service.security.model.SecurityUser; import javax.servlet.http.HttpServletRequest; diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index 44c7d94b3d..43ece89420 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 757f765dce..bf89f13a1c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/plugin/PluginApiController.java b/application/src/main/java/org/thingsboard/server/controller/plugin/PluginApiController.java index 045835e1b6..8d25db3702 100644 --- a/application/src/main/java/org/thingsboard/server/controller/plugin/PluginApiController.java +++ b/application/src/main/java/org/thingsboard/server/controller/plugin/PluginApiController.java @@ -17,31 +17,10 @@ package org.thingsboard.server.controller.plugin; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.async.DeferredResult; -import org.thingsboard.server.actors.service.ActorService; -import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.common.data.plugin.PluginMetaData; import org.thingsboard.server.controller.BaseController; -import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.plugin.PluginService; -import org.thingsboard.server.exception.ThingsboardException; -import org.thingsboard.server.extensions.api.plugins.PluginApiCallSecurityContext; import org.thingsboard.server.extensions.api.plugins.PluginConstants; -import org.thingsboard.server.extensions.api.plugins.rest.BasicPluginRestMsg; -import org.thingsboard.server.extensions.api.plugins.rest.RestRequest; - -import javax.servlet.http.HttpServletRequest; @RestController @RequestMapping(PluginConstants.PLUGIN_URL_PREFIX) diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java index 3b897d6bb3..031073fa97 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java @@ -16,6 +16,7 @@ package org.thingsboard.server.exception; import org.springframework.http.HttpStatus; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import java.util.Date; diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index c70c5612c3..63fe17ac4f 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -17,8 +17,6 @@ package org.thingsboard.server.exception; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -27,6 +25,8 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index 25b911c2d5..818c935595 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -27,13 +27,15 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.springframework.ui.velocity.VelocityEngineUtils; +import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.AdminSettings; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.settings.AdminSettingsService; -import org.thingsboard.server.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardException; import javax.annotation.PostConstruct; +import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.util.HashMap; import java.util.Locale; @@ -49,18 +51,18 @@ public class DefaultMailService implements MailService { public static final String UTF_8 = "UTF-8"; @Autowired private MessageSource messages; - + @Autowired @Qualifier("velocityEngine") private VelocityEngine engine; - + private JavaMailSenderImpl mailSender; - + private String mailFrom; - + @Autowired - private AdminSettingsService adminSettingsService; - + private AdminSettingsService adminSettingsService; + @PostConstruct private void init() { updateMailConfiguration(); @@ -77,7 +79,7 @@ public class DefaultMailService implements MailService { throw new IncorrectParameterException("Failed to date mail configuration. Settings not found!"); } } - + private JavaMailSenderImpl createMailSender(JsonNode jsonConfig) { JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost(jsonConfig.get("smtpHost").asText()); @@ -99,7 +101,7 @@ public class DefaultMailService implements MailService { javaMailProperties.put(MAIL_PROP + protocol + ".starttls.enable", jsonConfig.has("enableTls") ? jsonConfig.get("enableTls").asText() : "false"); return javaMailProperties; } - + private int parsePort(String strPort) { try { return Integer.valueOf(strPort); @@ -112,86 +114,102 @@ public class DefaultMailService implements MailService { public void sendEmail(String email, String subject, String message) throws ThingsboardException { sendMail(mailSender, mailFrom, email, subject, message); } - + @Override public void sendTestMail(JsonNode jsonConfig, String email) throws ThingsboardException { JavaMailSenderImpl testMailSender = createMailSender(jsonConfig); String mailFrom = jsonConfig.get("mailFrom").asText(); String subject = messages.getMessage("test.message.subject", null, Locale.US); - + Map model = new HashMap(); model.put(TARGET_EMAIL, email); - + String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, "test.vm", UTF_8, model); - - sendMail(testMailSender, mailFrom, email, subject, message); + + sendMail(testMailSender, mailFrom, email, subject, message); } @Override public void sendActivationEmail(String activationLink, String email) throws ThingsboardException { - + String subject = messages.getMessage("activation.subject", null, Locale.US); - + Map model = new HashMap(); model.put("activationLink", activationLink); model.put(TARGET_EMAIL, email); - + String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, "activation.vm", UTF_8, model); - - sendMail(mailSender, mailFrom, email, subject, message); + + sendMail(mailSender, mailFrom, email, subject, message); } - + @Override public void sendAccountActivatedEmail(String loginLink, String email) throws ThingsboardException { - + String subject = messages.getMessage("account.activated.subject", null, Locale.US); - + Map model = new HashMap(); model.put("loginLink", loginLink); model.put(TARGET_EMAIL, email); - + String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, "account.activated.vm", UTF_8, model); - - sendMail(mailSender, mailFrom, email, subject, message); + + sendMail(mailSender, mailFrom, email, subject, message); } @Override public void sendResetPasswordEmail(String passwordResetLink, String email) throws ThingsboardException { - + String subject = messages.getMessage("reset.password.subject", null, Locale.US); - + Map model = new HashMap(); model.put("passwordResetLink", passwordResetLink); model.put(TARGET_EMAIL, email); - + String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, "reset.password.vm", UTF_8, model); - - sendMail(mailSender, mailFrom, email, subject, message); + + sendMail(mailSender, mailFrom, email, subject, message); } - + @Override public void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException { - + String subject = messages.getMessage("password.was.reset.subject", null, Locale.US); - + Map model = new HashMap(); model.put("loginLink", loginLink); model.put(TARGET_EMAIL, email); - + String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, "password.was.reset.vm", UTF_8, model); - - sendMail(mailSender, mailFrom, email, subject, message); + + sendMail(mailSender, mailFrom, email, subject, message); } + @Override + public void send(String from, String to, String cc, String bcc, String subject, String body) throws MessagingException { + MimeMessage mailMsg = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mailMsg, "UTF-8"); + helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from); + helper.setTo(to.split("\\s*,\\s*")); + if (!StringUtils.isBlank(cc)) { + helper.setCc(cc.split("\\s*,\\s*")); + } + if (!StringUtils.isBlank(bcc)) { + helper.setBcc(bcc.split("\\s*,\\s*")); + } + helper.setSubject(subject); + helper.setText(body); + mailSender.send(helper.getMimeMessage()); + } - private void sendMail(JavaMailSenderImpl mailSender, - String mailFrom, String email, - String subject, String message) throws ThingsboardException { + private void sendMail(JavaMailSenderImpl mailSender, + String mailFrom, String email, + String subject, String message) throws ThingsboardException { try { MimeMessage mimeMsg = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMsg, UTF_8); @@ -208,7 +226,7 @@ public class DefaultMailService implements MailService { protected ThingsboardException handleException(Exception exception) { String message; if (exception instanceof NestedRuntimeException) { - message = ((NestedRuntimeException)exception).getMostSpecificCause().getMessage(); + message = ((NestedRuntimeException) exception).getMostSpecificCause().getMessage(); } else { message = exception.getMessage(); } diff --git a/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java b/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java new file mode 100644 index 0000000000..97c860694c --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/mail/MailExecutorService.java @@ -0,0 +1,54 @@ +/** + * 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.service.mail; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.thingsboard.rule.engine.api.ListeningExecutor; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; + +@Component +public class MailExecutorService implements ListeningExecutor { + + @Value("${actors.rule.mail_thread_pool_size}") + private int mailExecutorThreadPoolSize; + + private ListeningExecutorService service; + + @PostConstruct + public void init() { + this.service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(mailExecutorThreadPoolSize)); + } + + @PreDestroy + public void destroy() { + if (this.service != null) { + this.service.shutdown(); + } + } + + @Override + public ListenableFuture executeAsync(Callable task) { + return service.submit(task); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java index 6943940c74..c1f3688e92 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java +++ b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java @@ -45,7 +45,7 @@ import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.user.UserService; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.extensions.api.exception.ToErrorResponseEntity; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 4ffa99811d..b5011e2a20 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -221,6 +221,7 @@ actors: error_persist_frequency: "${ACTORS_RULE_ERROR_FREQUENCY:3000}" # Specify thread pool size for javascript executor service js_thread_pool_size: "${ACTORS_RULE_JS_THREAD_POOL_SIZE:10}" + mail_thread_pool_size: "${ACTORS_RULE_MAIL_THREAD_POOL_SIZE:10}" chain: # Errors for particular actor are persisted once per specified amount of milliseconds error_persist_frequency: "${ACTORS_RULE_CHAIN_ERROR_FREQUENCY:3000}" diff --git a/application/src/test/java/org/thingsboard/server/service/mail/TestMailService.java b/application/src/test/java/org/thingsboard/server/service/mail/TestMailService.java index ed3750d6ca..ba2bb65acd 100644 --- a/application/src/test/java/org/thingsboard/server/service/mail/TestMailService.java +++ b/application/src/test/java/org/thingsboard/server/service/mail/TestMailService.java @@ -22,7 +22,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.rule.engine.api.MailService; +import org.thingsboard.server.common.data.exception.ThingsboardException; @Profile("test") @Configuration diff --git a/application/src/test/java/org/thingsboard/server/service/script/NashornJsEngineTest.java b/application/src/test/java/org/thingsboard/server/service/script/NashornJsEngineTest.java new file mode 100644 index 0000000000..e6a48e2838 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/script/NashornJsEngineTest.java @@ -0,0 +1,151 @@ +/** + * 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.service.script; + +import com.datastax.driver.core.utils.UUIDs; +import com.google.common.collect.Sets; +import org.junit.Test; +import org.thingsboard.rule.engine.api.ScriptEngine; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; + +import javax.script.ScriptException; + +import java.util.Set; + +import static org.junit.Assert.*; + +public class NashornJsEngineTest { + + private ScriptEngine scriptEngine; + + @Test + public void msgCanBeUpdated() throws ScriptException { + String function = "metadata.temp = metadata.temp * 10; return {metadata: metadata};"; + scriptEngine = new NashornJsEngine(function, "Transform"); + + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "7"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + + TbMsg actual = scriptEngine.executeUpdate(msg); + assertEquals("70", actual.getMetaData().getValue("temp")); + } + + @Test + public void newAttributesCanBeAddedInMsg() throws ScriptException { + String function = "metadata.newAttr = metadata.humidity - msg.passed; return {metadata: metadata};"; + scriptEngine = new NashornJsEngine(function, "Transform"); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "7"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + + TbMsg actual = scriptEngine.executeUpdate(msg); + assertEquals("94", actual.getMetaData().getValue("newAttr")); + } + + @Test + public void payloadCanBeUpdated() throws ScriptException { + String function = "msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine'; return {msg: msg};"; + scriptEngine = new NashornJsEngine(function, "Transform"); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "7"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\":\"Vit\",\"passed\": 5,\"bigObj\":{\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + + TbMsg actual = scriptEngine.executeUpdate(msg); + + String expectedJson = "{\"name\":\"Vit\",\"passed\":35,\"bigObj\":{\"prop\":42,\"newProp\":\"Ukraine\"}}"; + assertEquals(expectedJson, actual.getData()); + } + + @Test + public void metadataAccessibleForFilter() throws ScriptException { + String function = "return metadata.humidity < 15;"; + scriptEngine = new NashornJsEngine(function, "Filter"); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "7"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + assertFalse(scriptEngine.executeFilter(msg)); + } + + @Test + public void dataAccessibleForFilter() throws ScriptException { + String function = "return msg.passed < 15 && msg.name === 'Vit' && metadata.temp == 7 && msg.bigObj.prop == 42;"; + scriptEngine = new NashornJsEngine(function, "Filter"); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "7"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + assertTrue(scriptEngine.executeFilter(msg)); + } + + @Test + public void dataAccessibleForSwitch() throws ScriptException { + String jsCode = "function nextRelation(metadata, msg) {\n" + + " if(msg.passed == 5 && metadata.temp == 10)\n" + + " return 'one'\n" + + " else\n" + + " return 'two';\n" + + "};\n" + + "\n" + + "return nextRelation(metadata, msg);"; + scriptEngine = new NashornJsEngine(jsCode, "Switch"); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "10"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + Set actual = scriptEngine.executeSwitch(msg); + assertEquals(Sets.newHashSet("one"), actual); + } + + @Test + public void multipleRelationsReturnedFromSwitch() throws ScriptException { + String jsCode = "function nextRelation(metadata, msg) {\n" + + " if(msg.passed == 5 && metadata.temp == 10)\n" + + " return ['three', 'one']\n" + + " else\n" + + " return 'two';\n" + + "};\n" + + "\n" + + "return nextRelation(metadata, msg);"; + scriptEngine = new NashornJsEngine(jsCode, "Switch"); + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("temp", "10"); + metaData.putValue("humidity", "99"); + String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; + + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); + Set actual = scriptEngine.executeSwitch(msg); + assertEquals(Sets.newHashSet("one", "three"), actual); + } + +} \ No newline at end of file diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/User.java b/common/data/src/main/java/org/thingsboard/server/common/data/User.java index 7b016f540e..15c52dc49c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/User.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/User.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.CustomerId; @@ -139,14 +140,17 @@ public class User extends SearchTextBasedWithAdditionalInfo implements H return builder.toString(); } + @JsonIgnore public boolean isSystemAdmin() { return tenantId == null || EntityId.NULL_UUID.equals(tenantId.getId()); } + @JsonIgnore public boolean isTenantAdmin() { return !isSystemAdmin() && (customerId == null || EntityId.NULL_UUID.equals(customerId.getId())); } + @JsonIgnore public boolean isCustomerUser() { return !isSystemAdmin() && !isTenantAdmin(); } diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorCode.java b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java similarity index 95% rename from application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorCode.java rename to common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java index e78d4f208a..5b7cfb9864 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorCode.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.exception; +package org.thingsboard.server.common.data.exception; import com.fasterxml.jackson.annotation.JsonValue; diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardException.java b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardException.java similarity index 96% rename from application/src/main/java/org/thingsboard/server/exception/ThingsboardException.java rename to common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardException.java index fcbd65eb27..fe4bd502e0 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardException.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.exception; +package org.thingsboard.server.common.data.exception; public class ThingsboardException extends Exception { diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java index ce13e23e17..4b7314c233 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java @@ -45,6 +45,10 @@ public final class TbMsgMetaData implements Serializable { data.put(key, value); } + public Map values() { + return new HashMap<>(data); + } + public TbMsgMetaData copy() { return new TbMsgMetaData(new ConcurrentHashMap<>(data)); } diff --git a/application/src/main/java/org/thingsboard/server/service/mail/MailService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java similarity index 80% rename from application/src/main/java/org/thingsboard/server/service/mail/MailService.java rename to rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java index b87da4c106..02ce780293 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/MailService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.mail; +package org.thingsboard.rule.engine.api; -import org.thingsboard.server.exception.ThingsboardException; +import org.thingsboard.server.common.data.exception.ThingsboardException; import com.fasterxml.jackson.databind.JsonNode; +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; + public interface MailService { void updateMailConfiguration(); @@ -34,5 +37,6 @@ public interface MailService { void sendResetPasswordEmail(String passwordResetLink, String email) throws ThingsboardException; void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException; - + + void send(String from, String to, String cc, String bcc, String subject, String body) throws MessagingException; } diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index 258b173bb5..fcc9b5c03c 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -86,6 +86,10 @@ public interface TbContext { ListeningExecutor getJsExecutor(); + ListeningExecutor getMailExecutor(); + + MailService getMailService(); + ScriptEngine createJsScriptEngine(String script, String functionName, String... argNames); } diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 3deea9b180..419b5f6ef3 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -71,6 +71,16 @@ com.google.guava guava + + org.apache.velocity + velocity + provided + + + org.apache.velocity + velocity-tools + provided + junit junit diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/EmailPojo.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/EmailPojo.java new file mode 100644 index 0000000000..35eaa3b14b --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/EmailPojo.java @@ -0,0 +1,32 @@ +/** + * 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.rule.engine.mail; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +class EmailPojo { + + private final String from; + private final String to; + private final String cc; + private final String bcc; + private final String subject; + private final String body; + +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/RuleVelocityUtils.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/RuleVelocityUtils.java new file mode 100644 index 0000000000..7413cadd48 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/RuleVelocityUtils.java @@ -0,0 +1,68 @@ +/** + * 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.rule.engine.mail; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.runtime.RuntimeServices; +import org.apache.velocity.runtime.RuntimeSingleton; +import org.apache.velocity.runtime.parser.ParseException; +import org.apache.velocity.runtime.parser.node.SimpleNode; +import org.thingsboard.server.common.msg.TbMsg; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; + +import static org.thingsboard.server.common.msg.TbMsgDataType.JSON; + +public class RuleVelocityUtils { + + public static VelocityContext createContext(TbMsg msg) throws IOException { + VelocityContext context = new VelocityContext(); + context.put("originator", msg.getOriginator()); + context.put("type", msg.getType()); + context.put("metadata", msg.getMetaData().values()); + if (msg.getDataType() == JSON) { + Map map = new ObjectMapper().readValue(msg.getData(), Map.class); + context.put("msg", map); + } else { + context.put("msg", msg.getData()); + } + return context; + } + + public static String merge(Template template, VelocityContext context) { + StringWriter writer = new StringWriter(); + template.merge(context, writer); + return writer.toString(); + } + + public static Template create(String source, String templateName) throws ParseException { + RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices(); + StringReader reader = new StringReader(source); + SimpleNode node = runtimeServices.parse(reader, templateName); + Template template = new Template(); + template.setRuntimeServices(runtimeServices); + template.setData(node); + template.initDocument(); + return template; + } + + +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java new file mode 100644 index 0000000000..a35e694bde --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.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.rule.engine.mail; + +import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.runtime.parser.ParseException; +import org.springframework.util.StringUtils; +import org.thingsboard.rule.engine.TbNodeUtils; +import org.thingsboard.rule.engine.api.*; +import org.thingsboard.server.common.data.plugin.ComponentType; +import org.thingsboard.server.common.msg.TbMsg; + +import java.io.IOException; +import java.util.Optional; + +import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE; + +@Slf4j +@RuleNode( + type = ComponentType.TRANSFORMATION, + name = "to email", + configClazz = TbMsgToEmailNodeConfiguration.class, + nodeDescription = "Change Message Originator To Tenant/Customer/Related Entity", + nodeDetails = "Related Entity found using configured relation direction and Relation Type. " + + "If multiple Related Entities are found, only first Entity is used as new Originator, other entities are discarded. ") +public class TbMsgToEmailNode implements TbNode { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private TbMsgToEmailNodeConfiguration config; + + private Optional