Commit c81854e61467d768fd631c6ea35d7c76ec7daeae
1 parent
72374979
Twilio SMS provider added support Phone Number's SID or Messaging Service SID
Showing
6 changed files
with
24 additions
and
11 deletions
@@ -25,6 +25,7 @@ import java.util.regex.Pattern; | @@ -25,6 +25,7 @@ import java.util.regex.Pattern; | ||
25 | public abstract class AbstractSmsSender implements SmsSender { | 25 | public abstract class AbstractSmsSender implements SmsSender { |
26 | 26 | ||
27 | private static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); | 27 | private static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); |
28 | + private static final Pattern PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID = Pattern.compile("^(PN|MG).*$"); | ||
28 | 29 | ||
29 | private static final int MAX_SMS_MESSAGE_LENGTH = 1600; | 30 | private static final int MAX_SMS_MESSAGE_LENGTH = 1600; |
30 | private static final int MAX_SMS_SEGMENT_LENGTH = 70; | 31 | private static final int MAX_SMS_SEGMENT_LENGTH = 70; |
@@ -37,6 +38,14 @@ public abstract class AbstractSmsSender implements SmsSender { | @@ -37,6 +38,14 @@ public abstract class AbstractSmsSender implements SmsSender { | ||
37 | return phoneNumber; | 38 | return phoneNumber; |
38 | } | 39 | } |
39 | 40 | ||
41 | + protected String validatePhoneTwilioNumber(String phoneNumber) throws SmsParseException { | ||
42 | + phoneNumber = phoneNumber.trim(); | ||
43 | + if (!E_164_PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches() && !PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID.matcher(phoneNumber).matches()) { | ||
44 | + throw new SmsParseException("Invalid phone number format. Phone number must be in E.164 format/Phone Number's SID/Messaging Service SID."); | ||
45 | + } | ||
46 | + return phoneNumber; | ||
47 | + } | ||
48 | + | ||
40 | protected String prepareMessage(String message) { | 49 | protected String prepareMessage(String message) { |
41 | message = message.replaceAll("^\"|\"$", "").replaceAll("\\\\n", "\n"); | 50 | message = message.replaceAll("^\"|\"$", "").replaceAll("\\\\n", "\n"); |
42 | if (message.length() > MAX_SMS_MESSAGE_LENGTH) { | 51 | if (message.length() > MAX_SMS_MESSAGE_LENGTH) { |
@@ -33,7 +33,7 @@ public class TwilioSmsSender extends AbstractSmsSender { | @@ -33,7 +33,7 @@ public class TwilioSmsSender extends AbstractSmsSender { | ||
33 | if (StringUtils.isEmpty(config.getAccountSid()) || StringUtils.isEmpty(config.getAccountToken()) || StringUtils.isEmpty(config.getNumberFrom())) { | 33 | if (StringUtils.isEmpty(config.getAccountSid()) || StringUtils.isEmpty(config.getAccountToken()) || StringUtils.isEmpty(config.getNumberFrom())) { |
34 | throw new IllegalArgumentException("Invalid twilio sms provider configuration: accountSid, accountToken and numberFrom should be specified!"); | 34 | throw new IllegalArgumentException("Invalid twilio sms provider configuration: accountSid, accountToken and numberFrom should be specified!"); |
35 | } | 35 | } |
36 | - this.numberFrom = this.validatePhoneNumber(config.getNumberFrom()); | 36 | + this.numberFrom = this.validatePhoneTwilioNumber(config.getNumberFrom()); |
37 | this.twilioRestClient = new TwilioRestClient.Builder(config.getAccountSid(), config.getAccountToken()).build(); | 37 | this.twilioRestClient = new TwilioRestClient.Builder(config.getAccountSid(), config.getAccountToken()).build(); |
38 | } | 38 | } |
39 | 39 |
@@ -18,14 +18,14 @@ | @@ -18,14 +18,14 @@ | ||
18 | <form [formGroup]="twilioSmsProviderConfigurationFormGroup" style="padding-bottom: 16px;"> | 18 | <form [formGroup]="twilioSmsProviderConfigurationFormGroup" style="padding-bottom: 16px;"> |
19 | <mat-form-field class="mat-block"> | 19 | <mat-form-field class="mat-block"> |
20 | <mat-label translate>admin.number-from</mat-label> | 20 | <mat-label translate>admin.number-from</mat-label> |
21 | - <input type="tel" required [pattern]="phoneNumberPattern" matInput formControlName="numberFrom"> | 21 | + <input type="tel" required [pattern]="phoneNumberPatternTwilio" matInput formControlName="numberFrom"> |
22 | <mat-error *ngIf="twilioSmsProviderConfigurationFormGroup.get('numberFrom').hasError('required')"> | 22 | <mat-error *ngIf="twilioSmsProviderConfigurationFormGroup.get('numberFrom').hasError('required')"> |
23 | {{ 'admin.number-from-required' | translate }} | 23 | {{ 'admin.number-from-required' | translate }} |
24 | </mat-error> | 24 | </mat-error> |
25 | <mat-error *ngIf="twilioSmsProviderConfigurationFormGroup.get('numberFrom').hasError('pattern')"> | 25 | <mat-error *ngIf="twilioSmsProviderConfigurationFormGroup.get('numberFrom').hasError('pattern')"> |
26 | - {{ 'admin.phone-number-pattern' | translate }} | 26 | + {{ 'admin.phone-number-pattern-twilio' | translate }} |
27 | </mat-error> | 27 | </mat-error> |
28 | - <mat-hint innerHTML="{{ 'admin.phone-number-hint' | translate }}"></mat-hint> | 28 | + <mat-hint innerHTML="{{ 'admin.phone-number-hint-twilio' | translate }}"></mat-hint> |
29 | </mat-form-field> | 29 | </mat-form-field> |
30 | <mat-form-field class="mat-block"> | 30 | <mat-form-field class="mat-block"> |
31 | <mat-label translate>admin.twilio-account-sid</mat-label> | 31 | <mat-label translate>admin.twilio-account-sid</mat-label> |
@@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
36 | </mat-form-field> | 36 | </mat-form-field> |
37 | <mat-form-field class="mat-block"> | 37 | <mat-form-field class="mat-block"> |
38 | <mat-label translate>admin.twilio-account-token</mat-label> | 38 | <mat-label translate>admin.twilio-account-token</mat-label> |
39 | - <input required type="password" matInput formControlName="accountToken"> | 39 | + <input required type="password" autocomplete="new-password" matInput formControlName="accountToken"> |
40 | <mat-error *ngIf="twilioSmsProviderConfigurationFormGroup.get('accountToken').hasError('required')"> | 40 | <mat-error *ngIf="twilioSmsProviderConfigurationFormGroup.get('accountToken').hasError('required')"> |
41 | {{ 'admin.twilio-account-token-required' | translate }} | 41 | {{ 'admin.twilio-account-token-required' | translate }} |
42 | </mat-error> | 42 | </mat-error> |
@@ -21,8 +21,9 @@ import { AppState } from '@app/core/core.state'; | @@ -21,8 +21,9 @@ import { AppState } from '@app/core/core.state'; | ||
21 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; | 21 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
22 | import { isDefinedAndNotNull } from '@core/utils'; | 22 | import { isDefinedAndNotNull } from '@core/utils'; |
23 | import { | 23 | import { |
24 | - phoneNumberPattern, | ||
25 | - SmsProviderConfiguration, SmsProviderType, | 24 | + phoneNumberPatternTwilio, |
25 | + SmsProviderConfiguration, | ||
26 | + SmsProviderType, | ||
26 | TwilioSmsProviderConfiguration | 27 | TwilioSmsProviderConfiguration |
27 | } from '@shared/models/settings.models'; | 28 | } from '@shared/models/settings.models'; |
28 | 29 | ||
@@ -40,7 +41,7 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce | @@ -40,7 +41,7 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce | ||
40 | 41 | ||
41 | twilioSmsProviderConfigurationFormGroup: FormGroup; | 42 | twilioSmsProviderConfigurationFormGroup: FormGroup; |
42 | 43 | ||
43 | - phoneNumberPattern = phoneNumberPattern; | 44 | + phoneNumberPatternTwilio = phoneNumberPatternTwilio; |
44 | 45 | ||
45 | private requiredValue: boolean; | 46 | private requiredValue: boolean; |
46 | 47 | ||
@@ -71,9 +72,9 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce | @@ -71,9 +72,9 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce | ||
71 | 72 | ||
72 | ngOnInit() { | 73 | ngOnInit() { |
73 | this.twilioSmsProviderConfigurationFormGroup = this.fb.group({ | 74 | this.twilioSmsProviderConfigurationFormGroup = this.fb.group({ |
74 | - numberFrom: [null, [Validators.required, Validators.pattern(phoneNumberPattern)]], | ||
75 | - accountSid: [null, [Validators.required]], | ||
76 | - accountToken: [null, [Validators.required]] | 75 | + numberFrom: [null, [Validators.required, Validators.pattern(phoneNumberPatternTwilio)]], |
76 | + accountSid: [null, Validators.required], | ||
77 | + accountToken: [null, Validators.required] | ||
77 | }); | 78 | }); |
78 | this.twilioSmsProviderConfigurationFormGroup.valueChanges.subscribe(() => { | 79 | this.twilioSmsProviderConfigurationFormGroup.valueChanges.subscribe(() => { |
79 | this.updateModel(); | 80 | this.updateModel(); |
@@ -65,6 +65,7 @@ export interface UpdateMessage { | @@ -65,6 +65,7 @@ export interface UpdateMessage { | ||
65 | } | 65 | } |
66 | 66 | ||
67 | export const phoneNumberPattern = /^\+[1-9]\d{1,14}$/; | 67 | export const phoneNumberPattern = /^\+[1-9]\d{1,14}$/; |
68 | +export const phoneNumberPatternTwilio = /^\+[1-9]\d{1,14}$|^(MG|PN).*$/; | ||
68 | 69 | ||
69 | export enum SmsProviderType { | 70 | export enum SmsProviderType { |
70 | AWS_SNS = 'AWS_SNS', | 71 | AWS_SNS = 'AWS_SNS', |
@@ -122,7 +122,9 @@ | @@ -122,7 +122,9 @@ | ||
122 | "number-to": "Phone Number To", | 122 | "number-to": "Phone Number To", |
123 | "number-to-required": "Phone Number To is required.", | 123 | "number-to-required": "Phone Number To is required.", |
124 | "phone-number-hint": "Phone Number in E.164 format, ex. +19995550123", | 124 | "phone-number-hint": "Phone Number in E.164 format, ex. +19995550123", |
125 | + "phone-number-hint-twilio": "Phone Number in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX", | ||
125 | "phone-number-pattern": "Invalid phone number. Should be in E.164 format, ex. +19995550123.", | 126 | "phone-number-pattern": "Invalid phone number. Should be in E.164 format, ex. +19995550123.", |
127 | + "phone-number-pattern-twilio": "Invalid phone number. Should be in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX.", | ||
126 | "sms-message": "SMS message", | 128 | "sms-message": "SMS message", |
127 | "sms-message-required": "SMS message is required.", | 129 | "sms-message-required": "SMS message is required.", |
128 | "sms-message-max-length": "SMS message can't be longer 1600 characters", | 130 | "sms-message-max-length": "SMS message can't be longer 1600 characters", |