From 7fb08dfb2f4e84196009c8ffce9dd8a39b40a9d1 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 30 Jan 2024 22:46:32 +0000 Subject: [PATCH] refactor: config --- app/config/variables.php | 2 +- src/Appwrite/Platform/Workers/Messaging.php | 58 ++++++++++----------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/app/config/variables.php b/app/config/variables.php index 072e28b850..a04f99bc9c 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -441,7 +441,7 @@ return [ 'variables' => [ [ 'name' => '_APP_SMS_PROVIDER', - 'description' => "Provider used for delivering SMS for Phone authentication. Use the following format: '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, vonage and geosms.\n\nWhen using the geosms provider, you must specify a default adapter. The default adapter can be set by URL encoding a normal provider configuration and passing it as the `default` parameter of the geosms configuration. e.g. `sms://geosms?default=[ENCODED_PROVIDER_CONFIG]`\nTo set local providers, for a specific country calling code, URL encode a provider configuration and pass it as the `local-[CALLING_CODE]` parameter of the geosms configuration. e.g. `sms://geosms?local-91=[ENCODED_PROVIDER_CONFIG]`", + 'description' => "Provider used for delivering SMS for Phone authentication. Use the following format: '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.\n\nWhen using the using multiple providers, GEOSMS is enabled. With GEOSMS, the first adapter is used as the default adapter for calling codes, and subsequent adapters can add the `local` parameter to specify the calling code for which they are used: e.g. `sms://[user]:[pass]@twilio?local=default,sms://[user]:[pass]@msg91?local=91`", 'introduction' => '0.15.0', 'default' => '', 'required' => false, diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index d9079dbfcb..c82528a98d 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -20,7 +20,7 @@ use Utopia\Queue\Message; class Messaging extends Action { - private ?DSN $dsn = null; + private array $dsns = []; public static function getName(): string { @@ -32,9 +32,14 @@ class Messaging extends Action */ public function __construct() { - $provider = App::getEnv('_APP_SMS_PROVIDER', ''); - if (!empty($provider)) { - $this->dsn = new DSN($provider); + $providers = App::getEnv('_APP_SMS_PROVIDER', ''); + + if (!empty($providers)) { + $providers = explode(',', $providers); + + foreach ($providers as $provider) { + $this->dsns[] = new DSN($provider); + } } $this @@ -85,7 +90,10 @@ class Messaging extends Action return; } - $sms = self::createAdapterFromDSN($this->dsn); + $sms = count($this->dsns) > 1 + ? self::createGEOSMSAdapter($this->dsns) + : self::createAdapterFromDSN($this->dsns[0]); + $from = App::getEnv('_APP_SMS_FROM'); if (empty($from)) { @@ -129,45 +137,35 @@ class Messaging extends Action return new Twilio($dsn->getUser(), $dsn->getPassword(), $from); case 'vonage': return new Vonage($dsn->getUser(), $dsn->getPassword(), $from); - case 'geosms': - return self::createGEOSMSAdapter($dsn); default: throw new \Exception('Unknown SMS provider: ' . $dsn->getHost()); } } - protected static function createGEOSMSAdapter(DSN $dsn): GEOSMS + protected static function createGEOSMSAdapter(array $dsns): GEOSMS { - $defaultAdapter = self::createAdapterFromDSN(new DSN($dsn->getParam('default', ''))); + $defaultAdapter = self::createAdapterFromDSN($dsns[0]); $geosms = new GEOSMS($defaultAdapter); + $localDSNs = array_slice($dsns, 1); - $parameters = []; - \parse_str($dsn->getQuery(), $parameters); - unset($parameters['default']); - - foreach ($parameters as $parameter => $nestedDSN) { - // Extract the calling code in the format of local-callingCode - // e.g. ?local-1=twilio://... - $callingCodeMatches = []; - if (\preg_match('/^local-(\d+)$/', $parameter, $callingCodeMatches) !== 1) { - Console::warning('Ignoring invalid GEOSMS parameter: ' . $parameter); + /** @var DSN $localDSN */ + foreach ($localDSNs as $localDSN) { + + $localAdapter = null; + try { + $localAdapter = self::createAdapterFromDSN($localDSN); + } catch (\Exception) { + Console::warning('Unable to create adapter: ' . $localDSN->getHost()); continue; } - $dsn = null; - try { - $dsn = new DSN($nestedDSN); - } catch (\Exception $e) { - Console::warning('Ignoring invalid GEOSMS adapter DSN: ' . $nestedDSN); + $callingCode = $localDSN->getParam('local', ''); + if (empty($callingCode)) { + Console::warning('Unable to register adapter: ' . $localDSN->getHost() . '. Missing `local` parameter.'); continue; } - try { - $adapter = self::createAdapterFromDSN($dsn); - $geosms->setLocal($callingCodeMatches[1], $adapter); - } catch (\Exception $e) { - Console::warning('Ignoring invalid GEOSMS adapter: ' . $dsn->getHost()); - } + $geosms->setLocal($callingCode, $localAdapter); } return $geosms;