diff --git a/app/workers/mails.php b/app/workers/mails.php index 32fbcbcb66..1f7edf5db4 100644 --- a/app/workers/mails.php +++ b/app/workers/mails.php @@ -1,33 +1,45 @@ desc('Audits worker') - ->inject('message') - ->inject('dbForProject') - ->inject('register') - ->callback(fn($message, $dbForProject, $register) => $this->action($message, $dbForProject, $register)); - } +Authorization::disable(); +Authorization::setDefaultStatus(false); - public function action(Message $message, $dbForProject, $register): void - { +/** + * Returns true if all the required terms in a locale exist. False otherwise + * + * @param $locale + * @param $prefix + * + * @return bool + */ +Server::setResource('doesLocaleExist', function () { + return function (Locale $locale, string $prefix) { + if (!$locale->getText('emails.sender') || !$locale->getText("$prefix.hello") || !$locale->getText("$prefix.subject") || !$locale->getText("$prefix.body") || !$locale->getText("$prefix.footer") || !$locale->getText("$prefix.thanks") || !$locale->getText("$prefix.signature")) { + return false; + } + + return true; + }; +}); + +$server->job() + ->inject('message') + ->inject('doesLocaleExist') + ->inject('register') + ->action(function (Message $message, callable $doesLocaleExist, Registry $register) { $payload = $message->getPayload() ?? []; if (empty($payload)) { @@ -60,37 +72,37 @@ class Mails extends Action $locale = new Locale($payload['locale']); $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); - if (!$doesLocaleExist($locale, $prefix)) { - $locale->setDefault('en'); - } + if (!$doesLocaleExist($locale, $prefix)) { + $locale->setDefault('en'); + } $from = $project->isEmpty() || $project->getId() === 'console' ? '' : \sprintf($locale->getText('emails.sender'), $projectName); $body = Template::fromFile(__DIR__ . '/../config/locale/templates/email-base.tpl'); $subject = ''; - switch ($type) { - case MAIL_TYPE_CERTIFICATE: - $domain = $payload['domain']; - $error = $payload['error']; - $attempt = $payload['attempt']; + switch ($type) { + case MAIL_TYPE_CERTIFICATE: + $domain = $payload['domain']; + $error = $payload['error']; + $attempt = $payload['attempt']; - $subject = \sprintf($locale->getText("$prefix.subject"), $domain); - $body->setParam('{{domain}}', $domain); - $body->setParam('{{error}}', $error); - $body->setParam('{{attempt}}', $attempt); - break; - case MAIL_TYPE_INVITATION: - $subject = \sprintf($locale->getText("$prefix.subject"), $team->getAttribute('name'), $projectName); - $body->setParam('{{owner}}', $user->getAttribute('name')); - $body->setParam('{{team}}', $team->getAttribute('name')); - break; - case MAIL_TYPE_RECOVERY: - case MAIL_TYPE_VERIFICATION: - case MAIL_TYPE_MAGIC_SESSION: - $subject = $locale->getText("$prefix.subject"); - break; - default: - throw new Exception('Undefined Mail Type : ' . $type, 500); - } + $subject = \sprintf($locale->getText("$prefix.subject"), $domain); + $body->setParam('{{domain}}', $domain); + $body->setParam('{{error}}', $error); + $body->setParam('{{attempt}}', $attempt); + break; + case MAIL_TYPE_INVITATION: + $subject = \sprintf($locale->getText("$prefix.subject"), $team->getAttribute('name'), $projectName); + $body->setParam('{{owner}}', $user->getAttribute('name')); + $body->setParam('{{team}}', $team->getAttribute('name')); + break; + case MAIL_TYPE_RECOVERY: + case MAIL_TYPE_VERIFICATION: + case MAIL_TYPE_MAGIC_SESSION: + $subject = $locale->getText("$prefix.subject"); + break; + default: + throw new Exception('Undefined Mail Type : ' . $type, 500); + } $body ->setParam('{{subject}}', $subject) @@ -135,30 +147,12 @@ class Mails extends Action $mail->Body = $body; $mail->AltBody = \strip_tags($body); - try { - $mail->send(); - } catch (\Exception $error) { - throw new Exception('Error sending mail: ' . $error->getMessage(), 500); - } + try { + $mail->send(); + } catch (\Exception $error) { + throw new Exception('Error sending mail: ' . $error->getMessage(), 500); } + }); - -/** - * Returns true if all the required terms in a locale exist. False otherwise - * - * @param Locale $locale - * @param string $prefix - * @return bool - */ -private function doesLocaleExist(Locale $locale, string $prefix) -{ - - if (!$locale->getText('emails.sender') || !$locale->getText("$prefix.hello") || !$locale->getText("$prefix.subject") || !$locale->getText("$prefix.body") || !$locale->getText("$prefix.footer") || !$locale->getText("$prefix.thanks") || !$locale->getText("$prefix.signature")) { - return false; - } - - return true; -} - - -} \ No newline at end of file +$server->workerStart(); +$server->start(); diff --git a/bin/worker-messaging b/bin/worker-messaging index 51057bc5a5..b61cf310c8 100644 --- a/bin/worker-messaging +++ b/bin/worker-messaging @@ -1,10 +1,3 @@ #!/bin/sh -if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ] -then - REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" -else - REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}" -fi - -INTERVAL=1 QUEUE='v1-messaging' APP_INCLUDE='/usr/src/code/app/workers/messaging.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php \ No newline at end of file +QUEUE=v1-messaging php /usr/src/code/app/worker.php messaging $@ \ No newline at end of file diff --git a/src/Appwrite/Platform/Services/Workers.php b/src/Appwrite/Platform/Services/Workers.php index 9db2b38b32..597bb8fae0 100644 --- a/src/Appwrite/Platform/Services/Workers.php +++ b/src/Appwrite/Platform/Services/Workers.php @@ -6,6 +6,7 @@ use Utopia\Platform\Service; use Appwrite\Platform\Workers\Audits; use Appwrite\Platform\Workers\Webhooks; use Appwrite\Platform\Workers\Mails; +use Appwrite\Platform\Workers\Messaging; class Workers extends Service { @@ -16,6 +17,7 @@ class Workers extends Service ->addAction(Audits::getName(), new Audits()) ->addAction(Webhooks::getName(), new Webhooks()) ->addAction(Mails::getName(), new Mails()) + ->addAction(Messaging::getName(), new Messaging()) ; } } diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php new file mode 100644 index 0000000000..a58f8b171b --- /dev/null +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -0,0 +1,101 @@ +provider = App::getEnv('_APP_SMS_PROVIDER', ''); + $this->dsn = !empty($this->provider) ? new DSN($this->provider) : null; + $this->user = !empty($this->provider) ? $this->dsn->getUser() : ''; + $this->secret = !empty($this->provider) ? $this->dsn->getPassword() : ''; + + $this + ->desc('Messaging worker') + ->inject('message') + ->callback(fn($message) => $this->action($message)); + } + + public function action(Message $message): void + { + + $payload = $message->getPayload() ?? []; + + if (empty($payload)) { + throw new Exception('Missing payload'); + } + + if (empty($payload['recipient'])) { + throw new Exception('Missing recipient'); + } + + if (empty($payload['message'])) { + throw new Exception('Missing message'); + } + + $this->execute($payload['recipient'], $payload['message']); + } + + + private function execute(string $recipient, string $message) + { + $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 + }; + + $from = App::getEnv('_APP_SMS_FROM'); + + if (empty(App::getEnv('_APP_SMS_PROVIDER'))) { + Console::info('Skipped sms processing. No Phone provider has been set.'); + return; + } + + if (empty($from)) { + Console::info('Skipped sms processing. No phone number has been set.'); + return; + } + + $message = new SMS( + to: [$recipient], + content: $message, + from: $from, + ); + + try { + $sms->send($message); + } catch (\Exception $error) { + throw new Exception('Error sending message: ' . $error->getMessage(), 500); + } + } +}