Commit eb8975d504be5d02d52d7693c6afaba01da7982d

Authored by Andrii Shvaika
1 parent 031f579b

SMS Email Limits

@@ -34,6 +34,7 @@ import org.thingsboard.rule.engine.api.TbRelationTypes; @@ -34,6 +34,7 @@ import org.thingsboard.rule.engine.api.TbRelationTypes;
34 import org.thingsboard.rule.engine.api.sms.SmsSenderFactory; 34 import org.thingsboard.rule.engine.api.sms.SmsSenderFactory;
35 import org.thingsboard.server.actors.ActorSystemContext; 35 import org.thingsboard.server.actors.ActorSystemContext;
36 import org.thingsboard.server.actors.TbActorRef; 36 import org.thingsboard.server.actors.TbActorRef;
  37 +import org.thingsboard.server.common.data.ApiUsageRecordKey;
37 import org.thingsboard.server.common.data.Customer; 38 import org.thingsboard.server.common.data.Customer;
38 import org.thingsboard.server.common.data.DataConstants; 39 import org.thingsboard.server.common.data.DataConstants;
39 import org.thingsboard.server.common.data.Device; 40 import org.thingsboard.server.common.data.Device;
@@ -21,7 +21,6 @@ import freemarker.template.Template; @@ -21,7 +21,6 @@ import freemarker.template.Template;
21 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
22 import org.apache.commons.lang3.StringUtils; 22 import org.apache.commons.lang3.StringUtils;
23 import org.jetbrains.annotations.NotNull; 23 import org.jetbrains.annotations.NotNull;
24 -import org.springframework.beans.factory.annotation.Autowired;  
25 import org.springframework.context.MessageSource; 24 import org.springframework.context.MessageSource;
26 import org.springframework.core.NestedRuntimeException; 25 import org.springframework.core.NestedRuntimeException;
27 import org.springframework.mail.javamail.JavaMailSenderImpl; 26 import org.springframework.mail.javamail.JavaMailSenderImpl;
@@ -40,6 +39,8 @@ import org.thingsboard.server.common.data.id.EntityId; @@ -40,6 +39,8 @@ import org.thingsboard.server.common.data.id.EntityId;
40 import org.thingsboard.server.common.data.id.TenantId; 39 import org.thingsboard.server.common.data.id.TenantId;
41 import org.thingsboard.server.dao.exception.IncorrectParameterException; 40 import org.thingsboard.server.dao.exception.IncorrectParameterException;
42 import org.thingsboard.server.dao.settings.AdminSettingsService; 41 import org.thingsboard.server.dao.settings.AdminSettingsService;
  42 +import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
  43 +import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
43 44
44 import javax.annotation.PostConstruct; 45 import javax.annotation.PostConstruct;
45 import javax.mail.MessagingException; 46 import javax.mail.MessagingException;
@@ -58,18 +59,24 @@ public class DefaultMailService implements MailService { @@ -58,18 +59,24 @@ public class DefaultMailService implements MailService {
58 public static final String UTF_8 = "UTF-8"; 59 public static final String UTF_8 = "UTF-8";
59 public static final int _10K = 10000; 60 public static final int _10K = 10000;
60 public static final int _1M = 1000000; 61 public static final int _1M = 1000000;
61 - @Autowired  
62 - private MessageSource messages;  
63 62
64 - @Autowired  
65 - private Configuration freemarkerConfig; 63 + private final MessageSource messages;
  64 + private final Configuration freemarkerConfig;
  65 + private final AdminSettingsService adminSettingsService;
  66 + private final TbApiUsageStateService apiUsageStateService;
  67 + private final TbApiUsageClient apiUsageClient;
66 68
67 private JavaMailSenderImpl mailSender; 69 private JavaMailSenderImpl mailSender;
68 70
69 private String mailFrom; 71 private String mailFrom;
70 72
71 - @Autowired  
72 - private AdminSettingsService adminSettingsService; 73 + public DefaultMailService(MessageSource messages, Configuration freemarkerConfig, AdminSettingsService adminSettingsService, TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient) {
  74 + this.messages = messages;
  75 + this.freemarkerConfig = freemarkerConfig;
  76 + this.adminSettingsService = adminSettingsService;
  77 + this.apiUsageStateService = apiUsageStateService;
  78 + this.apiUsageClient = apiUsageClient;
  79 + }
73 80
74 @PostConstruct 81 @PostConstruct
75 private void init() { 82 private void init() {
@@ -148,8 +155,11 @@ public class DefaultMailService implements MailService { @@ -148,8 +155,11 @@ public class DefaultMailService implements MailService {
148 } 155 }
149 156
150 @Override 157 @Override
151 - public void sendEmail(String email, String subject, String message) throws ThingsboardException {  
152 - sendMail(mailSender, mailFrom, email, subject, message); 158 + public void sendEmail(TenantId tenantId, String email, String subject, String message) throws ThingsboardException {
  159 + if (apiUsageStateService.getApiUsageState(tenantId).isEmailSendEnabled()) {
  160 + sendMail(mailSender, mailFrom, email, subject, message);
  161 + apiUsageClient.report(tenantId, ApiUsageRecordKey.EMAIL_EXEC_COUNT, 1);
  162 + }
153 } 163 }
154 164
155 @Override 165 @Override
@@ -223,20 +233,23 @@ public class DefaultMailService implements MailService { @@ -223,20 +233,23 @@ public class DefaultMailService implements MailService {
223 } 233 }
224 234
225 @Override 235 @Override
226 - public void send(String from, String to, String cc, String bcc, String subject, String body) throws MessagingException {  
227 - MimeMessage mailMsg = mailSender.createMimeMessage();  
228 - MimeMessageHelper helper = new MimeMessageHelper(mailMsg, "UTF-8");  
229 - helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from);  
230 - helper.setTo(to.split("\\s*,\\s*"));  
231 - if (!StringUtils.isBlank(cc)) {  
232 - helper.setCc(cc.split("\\s*,\\s*"));  
233 - }  
234 - if (!StringUtils.isBlank(bcc)) {  
235 - helper.setBcc(bcc.split("\\s*,\\s*")); 236 + public void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body) throws MessagingException {
  237 + if (apiUsageStateService.getApiUsageState(tenantId).isEmailSendEnabled()) {
  238 + MimeMessage mailMsg = mailSender.createMimeMessage();
  239 + MimeMessageHelper helper = new MimeMessageHelper(mailMsg, "UTF-8");
  240 + helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from);
  241 + helper.setTo(to.split("\\s*,\\s*"));
  242 + if (!StringUtils.isBlank(cc)) {
  243 + helper.setCc(cc.split("\\s*,\\s*"));
  244 + }
  245 + if (!StringUtils.isBlank(bcc)) {
  246 + helper.setBcc(bcc.split("\\s*,\\s*"));
  247 + }
  248 + helper.setSubject(subject);
  249 + helper.setText(body);
  250 + mailSender.send(helper.getMimeMessage());
  251 + apiUsageClient.report(tenantId, ApiUsageRecordKey.EMAIL_EXEC_COUNT, 1);
236 } 252 }
237 - helper.setSubject(subject);  
238 - helper.setText(body);  
239 - mailSender.send(helper.getMimeMessage());  
240 } 253 }
241 254
242 @Override 255 @Override
@@ -17,7 +17,6 @@ package org.thingsboard.server.service.sms; @@ -17,7 +17,6 @@ package org.thingsboard.server.service.sms;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 -import org.springframework.beans.factory.annotation.Autowired;  
21 import org.springframework.core.NestedRuntimeException; 20 import org.springframework.core.NestedRuntimeException;
22 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
23 import org.thingsboard.rule.engine.api.SmsService; 22 import org.thingsboard.rule.engine.api.SmsService;
@@ -26,12 +25,15 @@ import org.thingsboard.rule.engine.api.sms.SmsSenderFactory; @@ -26,12 +25,15 @@ import org.thingsboard.rule.engine.api.sms.SmsSenderFactory;
26 import org.thingsboard.rule.engine.api.sms.config.SmsProviderConfiguration; 25 import org.thingsboard.rule.engine.api.sms.config.SmsProviderConfiguration;
27 import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest; 26 import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest;
28 import org.thingsboard.server.common.data.AdminSettings; 27 import org.thingsboard.server.common.data.AdminSettings;
  28 +import org.thingsboard.server.common.data.ApiUsageRecordKey;
29 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; 29 import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
30 import org.thingsboard.server.common.data.exception.ThingsboardException; 30 import org.thingsboard.server.common.data.exception.ThingsboardException;
31 import org.thingsboard.server.common.data.id.EntityId; 31 import org.thingsboard.server.common.data.id.EntityId;
32 import org.thingsboard.server.common.data.id.TenantId; 32 import org.thingsboard.server.common.data.id.TenantId;
33 import org.thingsboard.server.dao.settings.AdminSettingsService; 33 import org.thingsboard.server.dao.settings.AdminSettingsService;
34 import org.thingsboard.server.dao.util.mapping.JacksonUtil; 34 import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  35 +import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
  36 +import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
35 37
36 import javax.annotation.PostConstruct; 38 import javax.annotation.PostConstruct;
37 import javax.annotation.PreDestroy; 39 import javax.annotation.PreDestroy;
@@ -40,14 +42,20 @@ import javax.annotation.PreDestroy; @@ -40,14 +42,20 @@ import javax.annotation.PreDestroy;
40 @Slf4j 42 @Slf4j
41 public class DefaultSmsService implements SmsService { 43 public class DefaultSmsService implements SmsService {
42 44
43 - @Autowired  
44 - private SmsSenderFactory smsSenderFactory;  
45 -  
46 - @Autowired  
47 - private AdminSettingsService adminSettingsService; 45 + private final SmsSenderFactory smsSenderFactory;
  46 + private final AdminSettingsService adminSettingsService;
  47 + private final TbApiUsageStateService apiUsageStateService;
  48 + private final TbApiUsageClient apiUsageClient;
48 49
49 private SmsSender smsSender; 50 private SmsSender smsSender;
50 51
  52 + public DefaultSmsService(SmsSenderFactory smsSenderFactory, AdminSettingsService adminSettingsService, TbApiUsageStateService apiUsageStateService, TbApiUsageClient apiUsageClient) {
  53 + this.smsSenderFactory = smsSenderFactory;
  54 + this.adminSettingsService = adminSettingsService;
  55 + this.apiUsageStateService = apiUsageStateService;
  56 + this.apiUsageClient = apiUsageClient;
  57 + }
  58 +
51 @PostConstruct 59 @PostConstruct
52 private void init() { 60 private void init() {
53 updateSmsConfiguration(); 61 updateSmsConfiguration();
@@ -78,18 +86,26 @@ public class DefaultSmsService implements SmsService { @@ -78,18 +86,26 @@ public class DefaultSmsService implements SmsService {
78 } 86 }
79 } 87 }
80 88
81 - @Override  
82 - public void sendSms(String numberTo, String message) throws ThingsboardException { 89 + private int sendSms(String numberTo, String message) throws ThingsboardException {
83 if (this.smsSender == null) { 90 if (this.smsSender == null) {
84 throw new ThingsboardException("Unable to send SMS: no SMS provider configured!", ThingsboardErrorCode.GENERAL); 91 throw new ThingsboardException("Unable to send SMS: no SMS provider configured!", ThingsboardErrorCode.GENERAL);
85 } 92 }
86 - this.sendSms(this.smsSender, numberTo, message); 93 + return this.sendSms(this.smsSender, numberTo, message);
87 } 94 }
88 95
89 @Override 96 @Override
90 - public void sendSms(String[] numbersTo, String message) throws ThingsboardException {  
91 - for (String numberTo : numbersTo) {  
92 - this.sendSms(numberTo, message); 97 + public void sendSms(TenantId tenantId, String[] numbersTo, String message) throws ThingsboardException {
  98 + if (apiUsageStateService.getApiUsageState(tenantId).isSmsSendEnabled()) {
  99 + int smsCount = 0;
  100 + try {
  101 + for (String numberTo : numbersTo) {
  102 + smsCount += this.sendSms(numberTo, message);
  103 + }
  104 + } finally {
  105 + if (smsCount > 0) {
  106 + apiUsageClient.report(tenantId, ApiUsageRecordKey.SMS_EXEC_COUNT, smsCount);
  107 + }
  108 + }
93 } 109 }
94 } 110 }
95 111
@@ -21,7 +21,9 @@ public enum ApiFeature { @@ -21,7 +21,9 @@ public enum ApiFeature {
21 TRANSPORT("transportApiState", "Device API"), 21 TRANSPORT("transportApiState", "Device API"),
22 DB("dbApiState", "Telemetry persistence"), 22 DB("dbApiState", "Telemetry persistence"),
23 RE("ruleEngineApiState", "Rule Engine execution"), 23 RE("ruleEngineApiState", "Rule Engine execution"),
24 - JS("jsExecutionApiState", "JavaScript functions execution"); 24 + JS("jsExecutionApiState", "JavaScript functions execution"),
  25 + EMAIL("emailApiState", "Email messages"),
  26 + SMS("smsApiState", "SMS messages");
25 27
26 @Getter 28 @Getter
27 private final String apiStateKey; 29 private final String apiStateKey;
@@ -23,11 +23,15 @@ public enum ApiUsageRecordKey { @@ -23,11 +23,15 @@ public enum ApiUsageRecordKey {
23 TRANSPORT_DP_COUNT(ApiFeature.TRANSPORT, "transportDataPointsCount", "transportDataPointsLimit"), 23 TRANSPORT_DP_COUNT(ApiFeature.TRANSPORT, "transportDataPointsCount", "transportDataPointsLimit"),
24 STORAGE_DP_COUNT(ApiFeature.DB, "storageDataPointsCount", "storageDataPointsLimit"), 24 STORAGE_DP_COUNT(ApiFeature.DB, "storageDataPointsCount", "storageDataPointsLimit"),
25 RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"), 25 RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit"),
26 - JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"); 26 + JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit"),
  27 + EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit"),
  28 + SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit");
27 private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; 29 private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT};
28 private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; 30 private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT};
29 private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; 31 private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT};
30 private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; 32 private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT};
  33 + private static final ApiUsageRecordKey[] EMAIL_RECORD_KEYS = {EMAIL_EXEC_COUNT};
  34 + private static final ApiUsageRecordKey[] SMS_RECORD_KEYS = {SMS_EXEC_COUNT};
31 35
32 @Getter 36 @Getter
33 private final ApiFeature apiFeature; 37 private final ApiFeature apiFeature;
@@ -52,6 +56,10 @@ public enum ApiUsageRecordKey { @@ -52,6 +56,10 @@ public enum ApiUsageRecordKey {
52 return RE_RECORD_KEYS; 56 return RE_RECORD_KEYS;
53 case JS: 57 case JS:
54 return JS_RECORD_KEYS; 58 return JS_RECORD_KEYS;
  59 + case EMAIL:
  60 + return EMAIL_RECORD_KEYS;
  61 + case SMS:
  62 + return SMS_RECORD_KEYS;
55 default: 63 default:
56 return new ApiUsageRecordKey[]{}; 64 return new ApiUsageRecordKey[]{};
57 } 65 }
@@ -47,6 +47,12 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan @@ -47,6 +47,12 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
47 @Getter 47 @Getter
48 @Setter 48 @Setter
49 private ApiUsageStateValue jsExecState; 49 private ApiUsageStateValue jsExecState;
  50 + @Getter
  51 + @Setter
  52 + private ApiUsageStateValue emailExecState;
  53 + @Getter
  54 + @Setter
  55 + private ApiUsageStateValue smsExecState;
50 56
51 public ApiUsageState() { 57 public ApiUsageState() {
52 super(); 58 super();
@@ -64,6 +70,8 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan @@ -64,6 +70,8 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
64 this.dbStorageState = ur.getDbStorageState(); 70 this.dbStorageState = ur.getDbStorageState();
65 this.reExecState = ur.getReExecState(); 71 this.reExecState = ur.getReExecState();
66 this.jsExecState = ur.getJsExecState(); 72 this.jsExecState = ur.getJsExecState();
  73 + this.emailExecState = ur.getEmailExecState();
  74 + this.smsExecState = ur.getSmsExecState();
67 } 75 }
68 76
69 public boolean isTransportEnabled() { 77 public boolean isTransportEnabled() {
@@ -81,4 +89,12 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan @@ -81,4 +89,12 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
81 public boolean isJsExecEnabled() { 89 public boolean isJsExecEnabled() {
82 return !ApiUsageStateValue.DISABLED.equals(jsExecState); 90 return !ApiUsageStateValue.DISABLED.equals(jsExecState);
83 } 91 }
  92 +
  93 + public boolean isEmailSendEnabled(){
  94 + return !ApiUsageStateValue.DISABLED.equals(emailExecState);
  95 + }
  96 +
  97 + public boolean isSmsSendEnabled(){
  98 + return !ApiUsageStateValue.DISABLED.equals(smsExecState);
  99 + }
84 } 100 }
@@ -42,6 +42,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura @@ -42,6 +42,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
42 private long maxJSExecutions; 42 private long maxJSExecutions;
43 private long maxDPStorageDays; 43 private long maxDPStorageDays;
44 private int maxRuleNodeExecutionsPerMessage; 44 private int maxRuleNodeExecutionsPerMessage;
  45 + private long maxEmails;
  46 + private long maxSms;
45 47
46 private double warnThreshold; 48 private double warnThreshold;
47 49
@@ -58,6 +60,10 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura @@ -58,6 +60,10 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
58 return maxREExecutions; 60 return maxREExecutions;
59 case STORAGE_DP_COUNT: 61 case STORAGE_DP_COUNT:
60 return maxDPStorageDays; 62 return maxDPStorageDays;
  63 + case EMAIL_EXEC_COUNT:
  64 + return maxEmails;
  65 + case SMS_EXEC_COUNT:
  66 + return maxSms;
61 } 67 }
62 return 0L; 68 return 0L;
63 } 69 }
@@ -450,6 +450,8 @@ public class ModelConstants { @@ -450,6 +450,8 @@ public class ModelConstants {
450 public static final String API_USAGE_STATE_DB_STORAGE_COLUMN = "db_storage"; 450 public static final String API_USAGE_STATE_DB_STORAGE_COLUMN = "db_storage";
451 public static final String API_USAGE_STATE_RE_EXEC_COLUMN = "re_exec"; 451 public static final String API_USAGE_STATE_RE_EXEC_COLUMN = "re_exec";
452 public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec"; 452 public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec";
  453 + public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec";
  454 + public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec";
453 455
454 /** 456 /**
455 * Cassandra attributes and timeseries constants. 457 * Cassandra attributes and timeseries constants.
@@ -63,6 +63,12 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements @@ -63,6 +63,12 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
63 @Enumerated(EnumType.STRING) 63 @Enumerated(EnumType.STRING)
64 @Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_COLUMN) 64 @Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_COLUMN)
65 private ApiUsageStateValue jsExecState = ApiUsageStateValue.ENABLED; 65 private ApiUsageStateValue jsExecState = ApiUsageStateValue.ENABLED;
  66 + @Enumerated(EnumType.STRING)
  67 + @Column(name = ModelConstants.API_USAGE_STATE_EMAIL_EXEC_COLUMN)
  68 + private ApiUsageStateValue emailExecState = ApiUsageStateValue.ENABLED;
  69 + @Enumerated(EnumType.STRING)
  70 + @Column(name = ModelConstants.API_USAGE_STATE_SMS_EXEC_COLUMN)
  71 + private ApiUsageStateValue smsExecState = ApiUsageStateValue.ENABLED;
66 72
67 public ApiUsageStateEntity() { 73 public ApiUsageStateEntity() {
68 } 74 }
@@ -83,6 +89,8 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements @@ -83,6 +89,8 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
83 this.dbStorageState = ur.getDbStorageState(); 89 this.dbStorageState = ur.getDbStorageState();
84 this.reExecState = ur.getReExecState(); 90 this.reExecState = ur.getReExecState();
85 this.jsExecState = ur.getJsExecState(); 91 this.jsExecState = ur.getJsExecState();
  92 + this.emailExecState = ur.getEmailExecState();
  93 + this.smsExecState = ur.getSmsExecState();
86 } 94 }
87 95
88 @Override 96 @Override
@@ -99,6 +107,8 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements @@ -99,6 +107,8 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
99 ur.setDbStorageState(dbStorageState); 107 ur.setDbStorageState(dbStorageState);
100 ur.setReExecState(reExecState); 108 ur.setReExecState(reExecState);
101 ur.setJsExecState(jsExecState); 109 ur.setJsExecState(jsExecState);
  110 + ur.setEmailExecState(emailExecState);
  111 + ur.setSmsExecState(smsExecState);
102 return ur; 112 return ur;
103 } 113 }
104 114
@@ -78,6 +78,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A @@ -78,6 +78,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
78 apiUsageState.setReExecState(ApiUsageStateValue.ENABLED); 78 apiUsageState.setReExecState(ApiUsageStateValue.ENABLED);
79 apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED); 79 apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED);
80 apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED); 80 apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED);
  81 + apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED);
  82 + apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED);
81 apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId); 83 apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId);
82 84
83 ApiUsageState saved = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState); 85 ApiUsageState saved = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState);
@@ -416,5 +416,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( @@ -416,5 +416,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
416 db_storage varchar(32), 416 db_storage varchar(32),
417 re_exec varchar(32), 417 re_exec varchar(32),
418 js_exec varchar(32), 418 js_exec varchar(32),
  419 + email_exec varchar(32),
  420 + sms_exec varchar(32),
419 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) 421 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)
420 ); 422 );
@@ -442,6 +442,8 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( @@ -442,6 +442,8 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
442 db_storage varchar(32), 442 db_storage varchar(32),
443 re_exec varchar(32), 443 re_exec varchar(32),
444 js_exec varchar(32), 444 js_exec varchar(32),
  445 + email_exec varchar(32),
  446 + sms_exec varchar(32),
445 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) 447 CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)
446 ); 448 );
447 449
@@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.ApiFeature; @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.ApiFeature;
20 import org.thingsboard.server.common.data.ApiUsageStateMailMessage; 20 import org.thingsboard.server.common.data.ApiUsageStateMailMessage;
21 import org.thingsboard.server.common.data.ApiUsageStateValue; 21 import org.thingsboard.server.common.data.ApiUsageStateValue;
22 import org.thingsboard.server.common.data.exception.ThingsboardException; 22 import org.thingsboard.server.common.data.exception.ThingsboardException;
  23 +import org.thingsboard.server.common.data.id.TenantId;
23 24
24 import javax.mail.MessagingException; 25 import javax.mail.MessagingException;
25 26
@@ -27,7 +28,7 @@ public interface MailService { @@ -27,7 +28,7 @@ public interface MailService {
27 28
28 void updateMailConfiguration(); 29 void updateMailConfiguration();
29 30
30 - void sendEmail(String email, String subject, String message) throws ThingsboardException; 31 + void sendEmail(TenantId tenantId, String email, String subject, String message) throws ThingsboardException;
31 32
32 void sendTestMail(JsonNode config, String email) throws ThingsboardException; 33 void sendTestMail(JsonNode config, String email) throws ThingsboardException;
33 34
@@ -39,7 +40,7 @@ public interface MailService { @@ -39,7 +40,7 @@ public interface MailService {
39 40
40 void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException; 41 void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException;
41 42
42 - void send(String from, String to, String cc, String bcc, String subject, String body) throws MessagingException; 43 + void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body) throws MessagingException;
43 44
44 void sendAccountLockoutEmail( String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException; 45 void sendAccountLockoutEmail( String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException;
45 46
@@ -17,14 +17,13 @@ package org.thingsboard.rule.engine.api; @@ -17,14 +17,13 @@ package org.thingsboard.rule.engine.api;
17 17
18 import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest; 18 import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest;
19 import org.thingsboard.server.common.data.exception.ThingsboardException; 19 import org.thingsboard.server.common.data.exception.ThingsboardException;
  20 +import org.thingsboard.server.common.data.id.TenantId;
20 21
21 public interface SmsService { 22 public interface SmsService {
22 23
23 void updateSmsConfiguration(); 24 void updateSmsConfiguration();
24 25
25 - void sendSms(String numberTo, String message) throws ThingsboardException;  
26 -  
27 - void sendSms(String[] numbersTo, String message) throws ThingsboardException;; 26 + void sendSms(TenantId tenantId, String[] numbersTo, String message) throws ThingsboardException;;
28 27
29 void sendTestSms(TestSmsRequest testSmsRequest) throws ThingsboardException; 28 void sendTestSms(TestSmsRequest testSmsRequest) throws ThingsboardException;
30 29
@@ -19,6 +19,7 @@ import io.netty.channel.EventLoopGroup; @@ -19,6 +19,7 @@ import io.netty.channel.EventLoopGroup;
19 import org.springframework.data.redis.core.RedisTemplate; 19 import org.springframework.data.redis.core.RedisTemplate;
20 import org.thingsboard.common.util.ListeningExecutor; 20 import org.thingsboard.common.util.ListeningExecutor;
21 import org.thingsboard.rule.engine.api.sms.SmsSenderFactory; 21 import org.thingsboard.rule.engine.api.sms.SmsSenderFactory;
  22 +import org.thingsboard.server.common.data.ApiUsageRecordKey;
22 import org.thingsboard.server.common.data.Customer; 23 import org.thingsboard.server.common.data.Customer;
23 import org.thingsboard.server.common.data.Device; 24 import org.thingsboard.server.common.data.Device;
24 import org.thingsboard.server.common.data.DeviceProfile; 25 import org.thingsboard.server.common.data.DeviceProfile;
@@ -26,6 +26,7 @@ import org.thingsboard.rule.engine.api.TbNode; @@ -26,6 +26,7 @@ import org.thingsboard.rule.engine.api.TbNode;
26 import org.thingsboard.rule.engine.api.TbNodeConfiguration; 26 import org.thingsboard.rule.engine.api.TbNodeConfiguration;
27 import org.thingsboard.rule.engine.api.TbNodeException; 27 import org.thingsboard.rule.engine.api.TbNodeException;
28 import org.thingsboard.rule.engine.api.util.TbNodeUtils; 28 import org.thingsboard.rule.engine.api.util.TbNodeUtils;
  29 +import org.thingsboard.server.common.data.ApiUsageRecordKey;
29 import org.thingsboard.server.common.data.plugin.ComponentType; 30 import org.thingsboard.server.common.data.plugin.ComponentType;
30 import org.thingsboard.server.common.msg.TbMsg; 31 import org.thingsboard.server.common.msg.TbMsg;
31 32
@@ -87,7 +88,7 @@ public class TbSendEmailNode implements TbNode { @@ -87,7 +88,7 @@ public class TbSendEmailNode implements TbNode {
87 88
88 private void sendEmail(TbContext ctx, EmailPojo email) throws Exception { 89 private void sendEmail(TbContext ctx, EmailPojo email) throws Exception {
89 if (this.config.isUseSystemSmtpSettings()) { 90 if (this.config.isUseSystemSmtpSettings()) {
90 - ctx.getMailService().send(email.getFrom(), email.getTo(), email.getCc(), 91 + ctx.getMailService().send(ctx.getTenantId(), email.getFrom(), email.getTo(), email.getCc(),
91 email.getBcc(), email.getSubject(), email.getBody()); 92 email.getBcc(), email.getSubject(), email.getBody());
92 } else { 93 } else {
93 MimeMessage mailMsg = mailSender.createMimeMessage(); 94 MimeMessage mailMsg = mailSender.createMimeMessage();
@@ -23,6 +23,7 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; @@ -23,6 +23,7 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
23 import org.thingsboard.rule.engine.api.TbNodeException; 23 import org.thingsboard.rule.engine.api.TbNodeException;
24 import org.thingsboard.rule.engine.api.sms.SmsSender; 24 import org.thingsboard.rule.engine.api.sms.SmsSender;
25 import org.thingsboard.rule.engine.api.util.TbNodeUtils; 25 import org.thingsboard.rule.engine.api.util.TbNodeUtils;
  26 +import org.thingsboard.server.common.data.ApiUsageRecordKey;
26 import org.thingsboard.server.common.data.plugin.ComponentType; 27 import org.thingsboard.server.common.data.plugin.ComponentType;
27 import org.thingsboard.server.common.msg.TbMsg; 28 import org.thingsboard.server.common.msg.TbMsg;
28 29
@@ -75,7 +76,7 @@ public class TbSendSmsNode implements TbNode { @@ -75,7 +76,7 @@ public class TbSendSmsNode implements TbNode {
75 String message = TbNodeUtils.processPattern(this.config.getSmsMessageTemplate(), msg.getMetaData()); 76 String message = TbNodeUtils.processPattern(this.config.getSmsMessageTemplate(), msg.getMetaData());
76 String[] numbersToList = numbersTo.split(","); 77 String[] numbersToList = numbersTo.split(",");
77 if (this.config.isUseSystemSmsSettings()) { 78 if (this.config.isUseSystemSmsSettings()) {
78 - ctx.getSmsService().sendSms(numbersToList, message); 79 + ctx.getSmsService().sendSms(ctx.getTenantId(), numbersToList, message);
79 } else { 80 } else {
80 for (String numberTo : numbersToList) { 81 for (String numberTo : numbersToList) {
81 this.smsSender.sendSms(numberTo, message); 82 this.smsSender.sendSms(numberTo, message);