From e6c9dda01dd31ff019bf4b3dbe4b2b51a42559fd Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Wed, 8 Nov 2023 17:03:08 +0000 Subject: [PATCH] feat: use geosms --- app/config/variables.php | 9 ++++ app/init.php | 35 +++++++++----- app/views/install/compose.phtml | 1 + docker-compose.yml | 1 + src/Appwrite/Platform/Workers/Messaging.php | 52 +++++++++++++-------- 5 files changed, 68 insertions(+), 30 deletions(-) diff --git a/app/config/variables.php b/app/config/variables.php index 9d555bf013..5028f395e0 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -447,6 +447,15 @@ return [ 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_GEOSMS_PROVIDERS', + 'description' => "Comma seperated list of providers used for delivering SMS for Phone authentication. Use the following format: 'sms://[USER]:[SECRET]@[PROVIDER],sms://[USER]:[SECRET]@[PROVIDER]'.\n\nEnsure `[USER]` and `[SECRET]` are URL encoded if they contain any non-alphanumeric characters.\n\nAvailable providers are twilio, text-magic, telesign, msg91, and vonage.", + 'introduction' => '1.4.10', + 'default' => '', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_SMS_FROM', 'description' => 'Phone number used for sending out messages. Must start with a leading \'+\' and maximum of 15 digits without spaces (+123456789).', diff --git a/app/init.php b/app/init.php index e4b9e7573d..ee771f9432 100644 --- a/app/init.php +++ b/app/init.php @@ -1329,18 +1329,31 @@ App::setResource('passwordsDictionary', function ($register) { App::setResource('sms', function () { $dsn = new DSN(App::getEnv('_APP_SMS_PROVIDER')); - $user = $dsn->getUser(); - $secret = $dsn->getPassword(); + + if (empty(App::getEnv('_APP_GEOSMS_PROVIDERS'))) { + return match ($dsn->getHost()) { + 'mock' => new Mock($dsn->getUser(), $dsn->getPassword()), // used for tests + 'twilio' => new Twilio($dsn->getUser(), $dsn->getPassword()), + 'text-magic' => new TextMagic($dsn->getUser(), $dsn->getPassword()), + 'telesign' => new Telesign($dsn->getUser(), $dsn->getPassword()), + 'msg91' => new Msg91($dsn->getUser(), $dsn->getPassword()), + 'vonage' => new Vonage($dsn->getUser(), $dsn->getPassword()), + default => null + }; + } - return match ($dsn->getHost()) { - 'mock' => new Mock($user, $secret), // used for tests - 'twilio' => new Twilio($user, $secret), - 'text-magic' => new TextMagic($user, $secret), - 'telesign' => new Telesign($user, $secret), - 'msg91' => new Msg91($user, $secret), - 'vonage' => new Vonage($user, $secret), - default => null - }; + $geosmsProviders = explode(',', App::getEnv('_APP_GEOSMS_PROVIDERS', '')); + $geosmsDSNs = []; + + foreach ($geosmsProviders as $geosmsProvider) { + $dsn = new DSN($geosmsProvider); + $geosmsDSNs[$dsn->getHost()] = $dsn; + } + + $twilio = new Twilio($this->geosmsDSNs['twilio']->getUser(), $this->geosmsDSNs['twilio']->getPassword()); + $msg91 = new Msg91($this->geosmsDSNs['msg91']>getUser(), $this->geosmsDSNs['msg91']->getPassword()); + $sms = new GEOSMS($twilio); + return $sms->setLocal(CallingCode::INDIA, $msg91); }); App::setResource('servers', function () { diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 898b46b3a5..d60431f780 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -154,6 +154,7 @@ services: - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY - _APP_MAINTENANCE_RETENTION_SCHEDULES - _APP_SMS_PROVIDER + _ _APP_GEOSMS_PROVIDERS - _APP_SMS_FROM - _APP_GRAPHQL_MAX_BATCH_SIZE - _APP_GRAPHQL_MAX_COMPLEXITY diff --git a/docker-compose.yml b/docker-compose.yml index 42091e5e46..e5792804da 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -175,6 +175,7 @@ services: - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY - _APP_MAINTENANCE_RETENTION_SCHEDULES - _APP_SMS_PROVIDER + - _APP_GEOSMS_PROVIDERS - _APP_SMS_FROM - _APP_GRAPHQL_MAX_BATCH_SIZE - _APP_GRAPHQL_MAX_COMPLEXITY diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 76b86e4f0c..3a3b1ed03b 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -13,15 +13,15 @@ use Utopia\Messaging\Adapters\SMS\Telesign; use Utopia\Messaging\Adapters\SMS\TextMagic; use Utopia\Messaging\Adapters\SMS\Twilio; use Utopia\Messaging\Adapters\SMS\Vonage; +use Utopia\Messaging\Adapters\SMS\GEOSMS; +use Utopia\Messaging\Adapters\SMS\GEOSMS\CallingCode; use Utopia\Platform\Action; use Utopia\Queue\Message; class Messaging extends Action { - private ?DSN $dsn = null; - private string $user = ''; - private string $secret = ''; - private string $provider = ''; + private DSN $dsn; + private array $geosmsDSNs = []; public static function getName(): string { @@ -33,11 +33,17 @@ class Messaging extends Action */ public function __construct() { - $this->provider = App::getEnv('_APP_SMS_PROVIDER', ''); + $provider = App::getEnv('_APP_SMS_PROVIDER', ''); if (!empty($this->provider)) { - $this->dsn = new DSN($this->provider); - $this->user = $this->dsn->getUser(); - $this->secret = $this->dsn->getPassword(); + $this->provider = new DSN($provider); + } + + $geoProviders = App::getEnv('_APP_GEOSMS_PROVIDERS', ''); + if (!empty($geoProviders)) { + foreach (explode(',', $geoProviders) as $geoProvider) { + $dsn = new DSN($geoProvider); + $this->geosmsDSNs[$dsn->getHost()] = $dsn; + } } $this @@ -70,21 +76,29 @@ class Messaging extends Action return; } - $sms = match ($this->dsn->getHost()) { - 'mock' => new Mock($this->user, $this->secret), // used for tests - 'twilio' => new Twilio($this->user, $this->secret), - 'text-magic' => new TextMagic($this->user, $this->secret), - 'telesign' => new Telesign($this->user, $this->secret), - 'msg91' => new Msg91($this->user, $this->secret), - 'vonage' => new Vonage($this->user, $this->secret), - default => null - }; - - if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { + + if (empty(App::getEnv('_APP_SMS_PROVIDER') && empty(App::getEnv('_APP_GEOSMS_PROVIDERS')))) { Console::error('Skipped sms processing. No Phone provider has been set.'); return; } + if (empty(App::getEnv('_APP_GEOSMS_PROVIDERS'))) { + $sms = match ($this->dsn->getHost()) { + 'mock' => new Mock($this->dsn->getUser(), $this->dsn->getPassword()), // used for tests + 'twilio' => new Twilio($this->dsn->getUser(), $this->dsn->getPassword()), + 'text-magic' => new TextMagic($this->dsn->getUser(), $this->dsn->getPassword()), + 'telesign' => new Telesign($this->dsn->getUser(), $this->dsn->getPassword()), + 'msg91' => new Msg91($this->dsn->getUser(), $this->dsn->getPassword()), + 'vonage' => new Vonage($this->dsn->getUser(), $this->dsn->getPassword()), + default => null + }; + } else { + $twilio = new Twilio($this->geosmsDSNs['twilio']->getUser(), $this->geosmsDSNs['twilio']->getPassword()); + $msg91 = new Msg91($this->geosmsDSNs['msg91']>getUser(), $this->geosmsDSNs['msg91']->getPassword()); + $sms = new GEOSMS($twilio); + $sms->setLocal(CallingCode::INDIA, $msg91); + } + $from = App::getEnv('_APP_SMS_FROM'); if (empty($from)) {