From c81854e61467d768fd631c6ea35d7c76ec7daeae Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 1 Mar 2021 19:16:13 +0200 Subject: [PATCH 1/2] Twilio SMS provider added support Phone Number's SID or Messaging Service SID --- .../server/service/sms/AbstractSmsSender.java | 9 +++++++++ .../server/service/sms/twilio/TwilioSmsSender.java | 2 +- ...twilio-sms-provider-configuration.component.html | 8 ++++---- .../twilio-sms-provider-configuration.component.ts | 13 +++++++------ ui-ngx/src/app/shared/models/settings.models.ts | 1 + ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 ++ 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java index 1a7619aec8..d62965d117 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java @@ -25,6 +25,7 @@ import java.util.regex.Pattern; public abstract class AbstractSmsSender implements SmsSender { private static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); + private static final Pattern PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID = Pattern.compile("^(PN|MG).*$"); private static final int MAX_SMS_MESSAGE_LENGTH = 1600; private static final int MAX_SMS_SEGMENT_LENGTH = 70; @@ -37,6 +38,14 @@ public abstract class AbstractSmsSender implements SmsSender { return phoneNumber; } + protected String validatePhoneTwilioNumber(String phoneNumber) throws SmsParseException { + phoneNumber = phoneNumber.trim(); + if (!E_164_PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches() && !PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID.matcher(phoneNumber).matches()) { + throw new SmsParseException("Invalid phone number format. Phone number must be in E.164 format/Phone Number's SID/Messaging Service SID."); + } + return phoneNumber; + } + protected String prepareMessage(String message) { message = message.replaceAll("^\"|\"$", "").replaceAll("\\\\n", "\n"); if (message.length() > MAX_SMS_MESSAGE_LENGTH) { diff --git a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java index 27c441410c..c4bba6ab26 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java @@ -33,7 +33,7 @@ public class TwilioSmsSender extends AbstractSmsSender { if (StringUtils.isEmpty(config.getAccountSid()) || StringUtils.isEmpty(config.getAccountToken()) || StringUtils.isEmpty(config.getNumberFrom())) { throw new IllegalArgumentException("Invalid twilio sms provider configuration: accountSid, accountToken and numberFrom should be specified!"); } - this.numberFrom = this.validatePhoneNumber(config.getNumberFrom()); + this.numberFrom = this.validatePhoneTwilioNumber(config.getNumberFrom()); this.twilioRestClient = new TwilioRestClient.Builder(config.getAccountSid(), config.getAccountToken()).build(); } diff --git a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html index b6308223ac..3af73e8932 100644 --- a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html @@ -18,14 +18,14 @@
admin.number-from - + {{ 'admin.number-from-required' | translate }} - {{ 'admin.phone-number-pattern' | translate }} + {{ 'admin.phone-number-pattern-twilio' | translate }} - + admin.twilio-account-sid @@ -36,7 +36,7 @@ admin.twilio-account-token - + {{ 'admin.twilio-account-token-required' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts index 759b9448ee..f4c31cd442 100644 --- a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts @@ -21,8 +21,9 @@ import { AppState } from '@app/core/core.state'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { isDefinedAndNotNull } from '@core/utils'; import { - phoneNumberPattern, - SmsProviderConfiguration, SmsProviderType, + phoneNumberPatternTwilio, + SmsProviderConfiguration, + SmsProviderType, TwilioSmsProviderConfiguration } from '@shared/models/settings.models'; @@ -40,7 +41,7 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce twilioSmsProviderConfigurationFormGroup: FormGroup; - phoneNumberPattern = phoneNumberPattern; + phoneNumberPatternTwilio = phoneNumberPatternTwilio; private requiredValue: boolean; @@ -71,9 +72,9 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce ngOnInit() { this.twilioSmsProviderConfigurationFormGroup = this.fb.group({ - numberFrom: [null, [Validators.required, Validators.pattern(phoneNumberPattern)]], - accountSid: [null, [Validators.required]], - accountToken: [null, [Validators.required]] + numberFrom: [null, [Validators.required, Validators.pattern(phoneNumberPatternTwilio)]], + accountSid: [null, Validators.required], + accountToken: [null, Validators.required] }); this.twilioSmsProviderConfigurationFormGroup.valueChanges.subscribe(() => { this.updateModel(); diff --git a/ui-ngx/src/app/shared/models/settings.models.ts b/ui-ngx/src/app/shared/models/settings.models.ts index b4a428daf8..3877488671 100644 --- a/ui-ngx/src/app/shared/models/settings.models.ts +++ b/ui-ngx/src/app/shared/models/settings.models.ts @@ -65,6 +65,7 @@ export interface UpdateMessage { } export const phoneNumberPattern = /^\+[1-9]\d{1,14}$/; +export const phoneNumberPatternTwilio = /^\+[1-9]\d{1,14}$|^(MG|PN).*$/; export enum SmsProviderType { AWS_SNS = 'AWS_SNS', diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index dff58d17d0..223a0f026a 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -122,7 +122,9 @@ "number-to": "Phone Number To", "number-to-required": "Phone Number To is required.", "phone-number-hint": "Phone Number in E.164 format, ex. +19995550123", + "phone-number-hint-twilio": "Phone Number in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX", "phone-number-pattern": "Invalid phone number. Should be in E.164 format, ex. +19995550123.", + "phone-number-pattern-twilio": "Invalid phone number. Should be in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX.", "sms-message": "SMS message", "sms-message-required": "SMS message is required.", "sms-message-max-length": "SMS message can't be longer 1600 characters", From 07ed2581bea769dbbad1848448041d97f566264b Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 3 Mar 2021 11:52:19 +0200 Subject: [PATCH 2/2] UI: Refactoring code --- .../server/service/sms/AbstractSmsSender.java | 11 +---------- .../server/service/sms/twilio/TwilioSmsSender.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java index d62965d117..84aa972e8a 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java @@ -24,8 +24,7 @@ import java.util.regex.Pattern; @Slf4j public abstract class AbstractSmsSender implements SmsSender { - private static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); - private static final Pattern PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID = Pattern.compile("^(PN|MG).*$"); + protected static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); private static final int MAX_SMS_MESSAGE_LENGTH = 1600; private static final int MAX_SMS_SEGMENT_LENGTH = 70; @@ -38,14 +37,6 @@ public abstract class AbstractSmsSender implements SmsSender { return phoneNumber; } - protected String validatePhoneTwilioNumber(String phoneNumber) throws SmsParseException { - phoneNumber = phoneNumber.trim(); - if (!E_164_PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches() && !PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID.matcher(phoneNumber).matches()) { - throw new SmsParseException("Invalid phone number format. Phone number must be in E.164 format/Phone Number's SID/Messaging Service SID."); - } - return phoneNumber; - } - protected String prepareMessage(String message) { message = message.replaceAll("^\"|\"$", "").replaceAll("\\\\n", "\n"); if (message.length() > MAX_SMS_MESSAGE_LENGTH) { diff --git a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java index c4bba6ab26..1988013fb0 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java @@ -19,16 +19,29 @@ import com.twilio.http.TwilioRestClient; import com.twilio.rest.api.v2010.account.Message; import com.twilio.type.PhoneNumber; import org.apache.commons.lang3.StringUtils; +import org.thingsboard.rule.engine.api.sms.exception.SmsParseException; import org.thingsboard.server.common.data.sms.config.TwilioSmsProviderConfiguration; import org.thingsboard.rule.engine.api.sms.exception.SmsException; import org.thingsboard.rule.engine.api.sms.exception.SmsSendException; import org.thingsboard.server.service.sms.AbstractSmsSender; +import java.util.regex.Pattern; + public class TwilioSmsSender extends AbstractSmsSender { + private static final Pattern PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID = Pattern.compile("^(PN|MG).*$"); + private TwilioRestClient twilioRestClient; private String numberFrom; + private String validatePhoneTwilioNumber(String phoneNumber) throws SmsParseException { + phoneNumber = phoneNumber.trim(); + if (!E_164_PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches() && !PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID.matcher(phoneNumber).matches()) { + throw new SmsParseException("Invalid phone number format. Phone number must be in E.164 format/Phone Number's SID/Messaging Service SID."); + } + return phoneNumber; + } + public TwilioSmsSender(TwilioSmsProviderConfiguration config) { if (StringUtils.isEmpty(config.getAccountSid()) || StringUtils.isEmpty(config.getAccountToken()) || StringUtils.isEmpty(config.getNumberFrom())) { throw new IllegalArgumentException("Invalid twilio sms provider configuration: accountSid, accountToken and numberFrom should be specified!");