From 06daa544e892b6e8b2975a4226d3045d7fc1c96a Mon Sep 17 00:00:00 2001 From: prateek banga Date: Mon, 30 Oct 2023 23:37:57 +0530 Subject: [PATCH 1/7] review changes --- app/config/collections.php | 42 ++- app/config/errors.php | 5 + app/controllers/api/account.php | 8 +- app/controllers/api/messaging.php | 294 ++++++++++++++---- app/controllers/api/teams.php | 4 +- composer.lock | 2 +- src/Appwrite/Extend/Exception.php | 1 + src/Appwrite/Platform/Workers/Messaging.php | 43 ++- .../Database/Validator/Queries/Messages.php | 4 +- .../Database/Validator/Queries/Providers.php | 2 +- .../Utopia/Response/Model/Message.php | 22 +- .../Utopia/Response/Model/Provider.php | 2 +- .../Account/AccountCustomClientTest.php | 5 +- tests/e2e/Services/GraphQL/AccountTest.php | 1 - tests/e2e/Services/GraphQL/Base.php | 112 ++++--- tests/e2e/Services/GraphQL/MessagingTest.php | 24 +- .../e2e/Services/Messaging/MessagingBase.php | 24 +- 17 files changed, 421 insertions(+), 174 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 54b6b3bec3..cf21df2ebf 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1417,7 +1417,7 @@ $commonCollections = [ 'filters' => [], ], [ - '$id' => ID::custom('default'), + '$id' => ID::custom('internal'), 'type' => Database::VAR_BOOLEAN, 'signed' => true, 'size' => 0, @@ -1495,16 +1495,16 @@ $commonCollections = [ 'orders' => [Database::ORDER_ASC], ], [ - '$id' => ID::custom('_key_default'), + '$id' => ID::custom('_key_internal'), 'type' => Database::INDEX_KEY, - 'attributes' => ['default'], + 'attributes' => ['internal'], 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], [ - '$id' => ID::custom('_key_default_type'), + '$id' => ID::custom('_key_internal_type'), 'type' => Database::INDEX_KEY, - 'attributes' => ['default','type'], + 'attributes' => ['internal','type'], 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], @@ -1557,13 +1557,35 @@ $commonCollections = [ 'filters' => ['json'], ], [ - '$id' => ID::custom('to'), + '$id' => ID::custom('topics'), 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 65535, + 'size' => 21845, 'signed' => true, - 'required' => true, - 'default' => null, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('users'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], 'array' => true, 'filters' => [], ], @@ -1601,7 +1623,7 @@ $commonCollections = [ 'filters' => [], ], [ - '$id' => ID::custom('deliveredTo'), + '$id' => ID::custom('deliveredTotal'), 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, diff --git a/app/config/errors.php b/app/config/errors.php index 50c59b23ec..931d24d65c 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -790,6 +790,11 @@ return [ 'description' => 'Message with the requested ID could not be found.', 'code' => 404, ], + Exception::MESSAGE_MISSING_TARGET => [ + 'name' => Exception::MESSAGE_MISSING_TARGET, + 'description' => 'Message with the requested ID is missing a target (Topics or Users or Targets).', + 'code' => 400, + ], Exception::MESSAGE_ALREADY_SENT => [ 'name' => Exception::MESSAGE_ALREADY_SENT, 'description' => 'Message with the requested ID has already been sent.', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 4c7411d978..faa8623601 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1241,7 +1241,7 @@ App::post('/v1/account/sessions/phone') ->inject('locale') ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])); if ($provider === false || $provider->isEmpty()) { @@ -1347,7 +1347,7 @@ App::post('/v1/account/sessions/phone') $messageDoc = $dbForProject->createDocument('messages', new Document([ '$id' => $token->getId(), - 'to' => [$target->getId()], + 'targets' => [$target->getId()], 'data' => [ 'content' => $message, ], @@ -2914,7 +2914,7 @@ App::post('/v1/account/verification/phone') ->inject('locale') ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])); if ($provider === false || $provider->isEmpty()) { @@ -2980,7 +2980,7 @@ App::post('/v1/account/verification/phone') $messageDoc = $dbForProject->createDocument('messages', new Document([ '$id' => $verification->getId(), - 'to' => [$target->getId()], + 'targets' => [$target->getId()], 'data' => [ 'content' => $message, ], diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1dbb371a7f..567c8e2cd6 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -69,14 +69,14 @@ App::post('/v1/messaging/providers/mailgun') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['email']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -127,14 +127,14 @@ App::post('/v1/messaging/providers/sendgrid') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -187,14 +187,14 @@ App::post('/v1/messaging/providers/msg91') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -247,14 +247,14 @@ App::post('/v1/messaging/providers/telesign') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -307,14 +307,14 @@ App::post('/v1/messaging/providers/textmagic') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -367,14 +367,14 @@ App::post('/v1/messaging/providers/twilio') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -427,14 +427,14 @@ App::post('/v1/messaging/providers/vonage') ] ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -481,14 +481,14 @@ App::post('/v1/messaging/providers/fcm') ], ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['push']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -543,14 +543,14 @@ App::post('/v1/messaging/providers/apns') ], ]); - // Check if a default provider exists, if not, set this one as default + // Check if a internal provider exists, if not, set this one as internal if ( empty($dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['push']) ])) ) { - $provider->setAttribute('default', true); + $provider->setAttribute('internal', true); } try { @@ -647,13 +647,14 @@ App::patch('/v1/messaging/providers/mailgun/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('isEuRegion', null, new Boolean(), 'Set as eu region.', true) ->param('from', '', new Text(256), 'Sender email address.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) ->param('domain', '', new Text(0), 'Mailgun Domain.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, ?bool $isEuRegion, string $from, string $apiKey, string $domain, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -680,6 +681,10 @@ App::patch('/v1/messaging/providers/mailgun/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if ($isEuRegion === true || $isEuRegion === false) { @@ -698,6 +703,15 @@ App::patch('/v1/messaging/providers/mailgun/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -718,11 +732,12 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) ->param('from', '', new Text(256), 'Sender email address.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $apiKey, string $from, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $apiKey, string $from, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -749,6 +764,10 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + if (!empty($apiKey)) { $provider->setAttribute('credentials', [ 'apiKey' => $apiKey, @@ -757,6 +776,15 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -777,12 +805,13 @@ App::patch('/v1/messaging/providers/msg91/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('senderId', '', new Text(0), 'Msg91 Sender ID.', true) ->param('authKey', '', new Text(0), 'Msg91 Auth Key.', true) ->param('from', '', new Text(256), 'Sender number.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $senderId, string $authKey, string $from, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $senderId, string $authKey, string $from, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -809,6 +838,10 @@ App::patch('/v1/messaging/providers/msg91/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if (!empty($senderId)) { @@ -823,6 +856,15 @@ App::patch('/v1/messaging/providers/msg91/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -843,12 +885,13 @@ App::patch('/v1/messaging/providers/telesign/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('username', '', new Text(0), 'Telesign username.', true) ->param('password', '', new Text(0), 'Telesign password.', true) ->param('from', '', new Text(256), 'Sender number.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $username, string $password, string $from, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $username, string $password, string $from, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -875,6 +918,10 @@ App::patch('/v1/messaging/providers/telesign/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if (!empty($username)) { @@ -889,6 +936,15 @@ App::patch('/v1/messaging/providers/telesign/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -909,12 +965,13 @@ App::patch('/v1/messaging/providers/textmagic/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('username', '', new Text(0), 'Textmagic username.', true) ->param('apiKey', '', new Text(0), 'Textmagic apiKey.', true) ->param('from', '', new Text(256), 'Sender number.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $username, string $apiKey, string $from, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $username, string $apiKey, string $from, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -941,6 +998,10 @@ App::patch('/v1/messaging/providers/textmagic/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if (!empty($username)) { @@ -955,6 +1016,15 @@ App::patch('/v1/messaging/providers/textmagic/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -975,12 +1045,13 @@ App::patch('/v1/messaging/providers/twilio/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('accountSid', null, new Text(0), 'Twilio account secret ID.', true) ->param('authToken', null, new Text(0), 'Twilio authentication token.', true) ->param('from', '', new Text(256), 'Sender number.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $accountSid, string $authToken, string $from, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $accountSid, string $authToken, string $from, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1007,6 +1078,10 @@ App::patch('/v1/messaging/providers/twilio/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if (!empty($accountSid)) { @@ -1021,6 +1096,15 @@ App::patch('/v1/messaging/providers/twilio/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -1041,12 +1125,13 @@ App::patch('/v1/messaging/providers/vonage/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('apiKey', '', new Text(0), 'Vonage API key.', true) ->param('apiSecret', '', new Text(0), 'Vonage API secret.', true) ->param('from', '', new Text(256), 'Sender number.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $apiKey, string $apiSecret, string $from, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $apiKey, string $apiSecret, string $from, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1073,6 +1158,10 @@ App::patch('/v1/messaging/providers/vonage/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if (!empty($apiKey)) { @@ -1087,6 +1176,15 @@ App::patch('/v1/messaging/providers/vonage/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -1107,10 +1205,11 @@ App::patch('/v1/messaging/providers/fcm/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('serverKey', '', new Text(0), 'FCM Server Key.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $serverKey, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $serverKey, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1131,12 +1230,25 @@ App::patch('/v1/messaging/providers/fcm/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + if (!empty($serverKey)) { $provider->setAttribute('credentials', ['serverKey' => $serverKey]); } $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -1158,6 +1270,7 @@ App::patch('/v1/messaging/providers/apns/:providerId') ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) + ->param('internal', null, new Boolean(), 'Set as internal. Internal providers are used in services other than Messaging service such as Authentication service', true) ->param('authKey', '', new Text(0), 'APNS authentication key.', true) ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) ->param('teamId', '', new Text(0), 'APNS team ID.', true) @@ -1165,7 +1278,7 @@ App::patch('/v1/messaging/providers/apns/:providerId') ->param('endpoint', '', new Text(0), 'APNS endpoint.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, ?bool $internal, string $authKey, string $authKeyId, string $teamId, string $bundleId, string $endpoint, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1186,6 +1299,10 @@ App::patch('/v1/messaging/providers/apns/:providerId') $provider->setAttribute('enabled', $enabled); } + if ($internal === true) { + $provider->setAttribute('internal', $internal); + } + $credentials = $provider->getAttribute('credentials'); if (!empty($authKey)) { @@ -1212,6 +1329,15 @@ App::patch('/v1/messaging/providers/apns/:providerId') $provider = $dbForProject->updateDocument('providers', $provider->getId(), $provider); + if ($internal === true) { + $internalProvider = $dbForProject->findOne('providers', [ + 'internal' => true, + 'type' => 'email', + ]); + $internalProvider->setAttribute('internal', false); + $dbForProject->updateDocument('providers', $internalProvider->getId(), $internalProvider); + } + $response ->dynamic($provider, Response::MODEL_PROVIDER); }); @@ -1620,9 +1746,11 @@ App::post('/v1/messaging/messages/email') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('subject', '', new Text(998), 'Email Subject.') ->param('content', '', new Text(64230), 'Email Content.') + ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for message.', true) ->param('status', 'processing', new WhiteList(['draft', 'processing']), 'Message Status. Value must be either draft or processing.', true) ->param('html', false, new Boolean(), 'Is content of type HTML', true) @@ -1631,12 +1759,18 @@ App::post('/v1/messaging/messages/email') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $to, string $subject, string $content, string $description, string $status, bool $html, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, string $description, string $status, bool $html, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; + if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) { + throw new Exception(Exception::MESSAGE_MISSING_TARGET); + } + $message = $dbForProject->createDocument('messages', new Document([ '$id' => $messageId, - 'to' => $to, + 'topics' => $topics, + 'users' => $users, + 'targets' => $targets, 'description' => $description, 'data' => [ 'subject' => $subject, @@ -1673,8 +1807,10 @@ App::post('/v1/messaging/messages/sms') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('content', '', new Text(64230), 'SMS Content.') + ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('status', 'processing', new WhiteList(['draft', 'processing']), 'Message Status. Value must be either draft or processing.', true) ->param('deliveryTime', null, new DatetimeValidator(requireDateInFuture: true), 'Delivery time for message in ISO 8601 format. DateTime value must be in future.', true) @@ -1682,12 +1818,18 @@ App::post('/v1/messaging/messages/sms') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $to, string $content, string $description, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $content, array $topics, array $users, array $targets, string $description, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; + if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) { + throw new Exception(Exception::MESSAGE_MISSING_TARGET); + } + $message = $dbForProject->createDocument('messages', new Document([ '$id' => $messageId, - 'to' => $to, + 'topics' => $topics, + 'users' => $users, + 'targets' => $targets, 'description' => $description, 'data' => [ 'content' => $content, @@ -1722,9 +1864,11 @@ App::post('/v1/messaging/messages/push') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new CustomId(), 'Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.') - ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs or List of User IDs or List of Target IDs.') ->param('title', '', new Text(256), 'Title for push notification.') ->param('body', '', new Text(64230), 'Body for push notification.') + ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('data', null, new JSON(), 'Additional Data for push notification.', true) ->param('action', '', new Text(256), 'Action for push notification.', true) @@ -1739,9 +1883,13 @@ App::post('/v1/messaging/messages/push') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $to, string $title, string $body, string $description, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, string $description, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; + if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) { + throw new Exception(Exception::MESSAGE_MISSING_TARGET); + } + $pushData = [ 'title' => $title, 'body' => $body, @@ -1777,7 +1925,9 @@ App::post('/v1/messaging/messages/push') $message = $dbForProject->createDocument('messages', new Document([ '$id' => $messageId, - 'to' => $to, + 'topics' => $topics, + 'users' => $users, + 'targets' => $targets, 'description' => $description, 'deliveryTime' => $deliveryTime, 'data' => $pushData, @@ -1878,7 +2028,9 @@ App::patch('/v1/messaging/messages/email/:messageId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new UID(), 'Message ID.') - ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs or List of User IDs or List of Target IDs.', true) + ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('subject', '', new Text(998), 'Email Subject.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(64230), 'Email Content.', true) @@ -1889,7 +2041,7 @@ App::patch('/v1/messaging/messages/email/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $to, string $subject, string $description, string $content, string $status, bool $html, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, array $topics, array $users, array $targets, string $subject, string $description, string $content, string $status, bool $html, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -1904,8 +2056,16 @@ App::patch('/v1/messaging/messages/email/:messageId') throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED); } - if (\count($to) > 0) { - $message->setAttribute('to', $to); + if (\count($topics) > 0) { + $message->setAttribute('topics', $topics); + } + + if (\count($users) > 0) { + $message->setAttribute('users', $users); + } + + if (\count($targets) > 0) { + $message->setAttribute('targets', $targets); } $data = $message->getAttribute('data'); @@ -1965,7 +2125,9 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new UID(), 'Message ID.') - ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs or List of User IDs or List of Target IDs.', true) + ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(64230), 'Email Content.', true) ->param('status', '', new WhiteList(['draft', 'processing']), 'Message Status. Value must be either draft or processing.', true) @@ -1974,7 +2136,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $to, string $description, string $content, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, array $topics, array $users, array $targets, string $description, string $content, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -1989,8 +2151,16 @@ App::patch('/v1/messaging/messages/sms/:messageId') throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED); } - if (\count($to) > 0) { - $message->setAttribute('to', $to); + if (\count($topics) > 0) { + $message->setAttribute('topics', $topics); + } + + if (\count($users) > 0) { + $message->setAttribute('users', $users); + } + + if (\count($targets) > 0) { + $message->setAttribute('targets', $targets); } $data = $message->getAttribute('data'); @@ -2042,7 +2212,9 @@ App::patch('/v1/messaging/messages/push/:messageId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new UID(), 'Message ID.') - ->param('to', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs or List of User IDs or List of Target IDs.', true) + ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('title', '', new Text(256), 'Title for push notification.', true) ->param('body', '', new Text(64230), 'Body for push notification.', true) @@ -2058,7 +2230,7 @@ App::patch('/v1/messaging/messages/push/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $to, string $description, string $title, string $body, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, array $topics, array $users, array $targets, string $description, string $title, string $body, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -2073,8 +2245,16 @@ App::patch('/v1/messaging/messages/push/:messageId') throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED); } - if (\count($to) > 0) { - $message->setAttribute('to', $to); + if (\count($topics) > 0) { + $message->setAttribute('topics', $topics); + } + + if (\count($users) > 0) { + $message->setAttribute('users', $users); + } + + if (\count($targets) > 0) { + $message->setAttribute('targets', $targets); } $pushData = $message->getAttribute('data'); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index da2261fd50..a0975634d5 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -633,7 +633,7 @@ App::post('/v1/teams/:teamId/memberships') ; } elseif (!empty($phone)) { $provider = Authorization::skip(fn () => $dbForProject->findOne('providers', [ - Query::equal('default', [true]), + Query::equal('internal', [true]), Query::equal('type', ['sms']) ])); @@ -662,7 +662,7 @@ App::post('/v1/teams/:teamId/memberships') $messageDoc = $dbForProject->createDocument('messages', new Document([ // Here membership ID is used as message ID so that it can be used in test cases to verify the message '$id' => $membership->getId(), - 'to' => [$target->getId()], + 'targets' => [$target->getId()], 'data' => [ 'content' => $message, ], diff --git a/composer.lock b/composer.lock index 66e5e5a11b..560dfe7b20 100644 --- a/composer.lock +++ b/composer.lock @@ -5822,5 +5822,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 8d6dc6d29a..cef64ffce5 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -241,6 +241,7 @@ class Exception extends \Exception /** Message */ public const MESSAGE_NOT_FOUND = 'message_not_found'; + public const MESSAGE_MISSING_TARGET = 'message_missing_target'; public const MESSAGE_ALREADY_SENT = 'message_already_sent'; public const MESSAGE_ALREADY_SCHEDULED = 'message_already_scheduled'; diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 5ca5ebfc65..a56c98b5e5 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -10,6 +10,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Messaging\Adapters\SMS as SMSAdapter; use Utopia\Messaging\Adapters\SMS\Mock; use Utopia\Messaging\Adapters\SMS\Msg91; @@ -70,25 +71,33 @@ class Messaging extends Action private function processMessage(Database $dbForProject, Document $message): void { - $recipientsId = $message->getAttribute('to', []); + $topicsId = $message->getAttribute('topics', []); + $targetsId = $message->getAttribute('targets', []); + $usersId = $message->getAttribute('users', []); /** * @var Document[] $recipients */ $recipients = []; - $topics = $dbForProject->find('topics', [Query::equal('$id', $recipientsId)]); - foreach ($topics as $topic) { - $recipients = \array_merge($recipients, $topic->getAttribute('targets')); + if (\count($topicsId) > 0) { + $topics = $dbForProject->find('topics', [Query::equal('$id', $topicsId)]); + foreach ($topics as $topic) { + $recipients = \array_merge($recipients, $topic->getAttribute('targets')); + } } - $users = $dbForProject->find('users', [Query::equal('$id', $recipientsId)]); - foreach ($users as $user) { - $recipients = \array_merge($recipients, $user->getAttribute('targets')); + if (\count($usersId) > 0) { + $users = $dbForProject->find('users', [Query::equal('$id', $usersId)]); + foreach ($users as $user) { + $recipients = \array_merge($recipients, $user->getAttribute('targets')); + } } - $targets = $dbForProject->find('targets', [Query::equal('$id', $recipientsId)]); - $recipients = \array_merge($recipients, $targets); + if (\count($targetsId) > 0) { + $targets = $dbForProject->find('targets', [Query::equal('$id', $targetsId)]); + $recipients = \array_merge($recipients, $targets); + } $providers = []; foreach ($recipients as $recipient) { @@ -104,7 +113,7 @@ class Messaging extends Action */ $results = batch(\array_map(function ($providerId) use ($providers, $message, $dbForProject) { return function () use ($providerId, $providers, $message, $dbForProject) { - $provider = $dbForProject->getDocument('providers', $providerId); + $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); $identifiers = $providers[$providerId]; $adapter = match ($provider->getAttribute('type')) { 'sms' => $this->sms($provider), @@ -118,7 +127,7 @@ class Messaging extends Action $results = batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex) { return function () use ($batch, $message, $provider, $adapter, $batchIndex) { - $deliveredTo = 0; + $deliveredTotal = 0; $deliveryErrors = []; $messageData = clone $message; $messageData->setAttribute('to', $batch); @@ -130,13 +139,13 @@ class Messaging extends Action }; try { $adapter->send($data); - $deliveredTo += \count($batch); + $deliveredTotal += \count($batch); } catch (\Exception $e) { $deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage(); } finally { $batchIndex++; return [ - 'deliveredTo' => $deliveredTo, + 'deliveredTotal' => $deliveredTotal, 'deliveryErrors' => $deliveryErrors, ]; } @@ -149,10 +158,10 @@ class Messaging extends Action $results = array_merge(...$results); - $deliveredTo = 0; + $deliveredTotal = 0; $deliveryErrors = []; foreach ($results as $result) { - $deliveredTo += $result['deliveredTo']; + $deliveredTotal += $result['deliveredTotal']; $deliveryErrors = \array_merge($deliveryErrors, $result['deliveryErrors']); } $message->setAttribute('deliveryErrors', $deliveryErrors); @@ -162,8 +171,8 @@ class Messaging extends Action } else { $message->setAttribute('status', 'sent'); } - $message->setAttribute('to', $recipientsId); - $message->setAttribute('deliveredTo', $deliveredTo); + $message->removeAttribute('to'); + $message->setAttribute('deliveredTotal', $deliveredTotal); $message->setAttribute('deliveredAt', DateTime::now()); $dbForProject->updateDocument('messages', $message->getId(), $message); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Messages.php b/src/Appwrite/Utopia/Database/Validator/Queries/Messages.php index 4bff13ae19..dd043474a8 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Messages.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Messages.php @@ -5,7 +5,9 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Messages extends Base { public const ALLOWED_ATTRIBUTES = [ - 'to', + 'topics', + 'users', + 'targets', 'providerId', 'deliveredAt', 'deliveredTo', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php index 1fd6c9e9f8..7760acbdad 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Providers.php @@ -8,7 +8,7 @@ class Providers extends Base 'name', 'provider', 'type', - 'default', + 'internal', 'enabled', ]; diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 609aa4022e..7816c4bf5d 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -17,12 +17,26 @@ class Message extends Any 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('to', [ + ->addRule('topics', [ 'type' => self::TYPE_STRING, - 'description' => 'Message recipients.', + 'description' => 'Topic IDs set as recipients.', 'default' => '', 'array' => true, - 'example' => ['user-1'], + 'example' => ['5e5ea5c16897e'], + ]) + ->addRule('users', [ + 'type' => self::TYPE_STRING, + 'description' => 'User IDs set as recipients.', + 'default' => '', + 'array' => true, + 'example' => ['5e5ea5c16897e'], + ]) + ->addRule('targets', [ + 'type' => self::TYPE_STRING, + 'description' => 'Target IDs set as recipients.', + 'default' => '', + 'array' => true, + 'example' => ['5e5ea5c16897e'], ]) ->addRule('deliveryTime', [ 'type' => self::TYPE_DATETIME, @@ -46,7 +60,7 @@ class Message extends Any 'array' => true, 'example' => ['Failed to send message to target 5e5ea5c16897e: Credentials not valid.'], ]) - ->addRule('deliveredTo', [ + ->addRule('deliveredTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Number of recipients the message was delivered to.', 'default' => 0, diff --git a/src/Appwrite/Utopia/Response/Model/Provider.php b/src/Appwrite/Utopia/Response/Model/Provider.php index 552e9783e8..ba522951e7 100644 --- a/src/Appwrite/Utopia/Response/Model/Provider.php +++ b/src/Appwrite/Utopia/Response/Model/Provider.php @@ -28,7 +28,7 @@ class Provider extends Model 'default' => '', 'example' => 'mailgun', ]) - ->addRule('default', [ + ->addRule('internal', [ 'type' => self::TYPE_BOOLEAN, 'description' => 'Is this a pre-configured provider instance?', 'default' => false, diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 7f4cb84b05..c138f4049a 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -762,7 +762,6 @@ class AccountCustomClientTest extends Scope 'name' => 'Sms provider', 'senderId' => $senderId, 'authKey' => $authKey, - 'default' => true, 'from' => $from, ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -810,7 +809,7 @@ class AccountCustomClientTest extends Scope ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); @@ -1040,7 +1039,7 @@ class AccountCustomClientTest extends Scope ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); return \array_merge($data, [ diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 801be808c9..e42fe1bc6c 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -142,7 +142,6 @@ class AccountTest extends Scope 'from' => $from, 'senderId' => $senderId, 'authKey' => $authKey, - 'default' => true, ], ]; diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index bf6ae84f7f..45fc148497 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1790,7 +1790,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1801,7 +1801,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1812,7 +1812,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1823,7 +1823,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1834,7 +1834,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1845,7 +1845,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1856,7 +1856,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1867,7 +1867,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1878,7 +1878,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1891,7 +1891,7 @@ trait Base name provider type - default + internal enabled } } @@ -1903,7 +1903,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1914,7 +1914,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1925,7 +1925,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1936,7 +1936,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1947,7 +1947,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1958,7 +1958,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1969,7 +1969,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1980,7 +1980,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -1991,7 +1991,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -2002,7 +2002,7 @@ trait Base name provider type - default + internal enabled } }'; @@ -2087,40 +2087,46 @@ trait Base } }'; case self::$CREATE_EMAIL: - return 'mutation createEmail($messageId: String!, $to: [String!]!, $subject: String!, $content: String!, $status: String, $description: String, $html: Boolean, $deliveryTime: String) { - messagingCreateEmail(messageId: $messageId, to: $to, subject: $subject, content: $content, status: $status, description: $description, html: $html, deliveryTime: $deliveryTime) { + return 'mutation createEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String!, $content: String!, $status: String, $description: String, $html: Boolean, $deliveryTime: String) { + messagingCreateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, deliveryTime: $deliveryTime) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } }'; case self::$CREATE_SMS: - return 'mutation createSMS($messageId: String!, $to: [String!]!, $content: String!, $status: String, $description: String, $deliveryTime: String) { - messagingCreateSMS(messageId: $messageId, to: $to, content: $content, status: $status, description: $description, deliveryTime: $deliveryTime) { + return 'mutation createSMS($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $content: String!, $status: String, $description: String, $deliveryTime: String) { + messagingCreateSMS(messageId: $messageId, topics: $topics, users: $users, targets: $targets, content: $content, status: $status, description: $description, deliveryTime: $deliveryTime) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } }'; case self::$CREATE_PUSH_NOTIFICATION: - return 'mutation createPushNotification($messageId: String!, $to: [String!]!, $title: String!, $body: String!, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $description: String, $deliveryTime: String) { - messagingCreatePushNotification(messageId: $messageId, to: $to, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, description: $description, deliveryTime: $deliveryTime) { + return 'mutation createPushNotification($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $title: String!, $body: String!, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $description: String, $deliveryTime: String) { + messagingCreatePushNotification(messageId: $messageId, topics: $topics, users: $users, targets: $targets, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, description: $description, deliveryTime: $deliveryTime) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } @@ -2131,11 +2137,13 @@ trait Base total messages { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } @@ -2145,50 +2153,58 @@ trait Base return 'query getMessage($messageId: String!) { messagingGetMessage(messageId: $messageId) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } }'; case self::$UPDATE_EMAIL: - return 'mutation updateEmail($messageId: String!, $to: [String!], $subject: String, $content: String, $status: String, $description: String, $html: Boolean, $deliveryTime: String) { - messagingUpdateEmail(messageId: $messageId, to: $to, subject: $subject, content: $content, status: $status, description: $description, html: $html, deliveryTime: $deliveryTime) { + return 'mutation updateEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String, $content: String, $status: String, $description: String, $html: Boolean, $deliveryTime: String) { + messagingUpdateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, deliveryTime: $deliveryTime) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } }'; case self::$UPDATE_SMS: - return 'mutation updateSMS($messageId: String!, $to: [String!], $content: String, $status: String, $description: String, $deliveryTime: String) { - messagingUpdateSMS(messageId: $messageId, to: $to, content: $content, status: $status, description: $description, deliveryTime: $deliveryTime) { + return 'mutation updateSMS($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $content: String, $status: String, $description: String, $deliveryTime: String) { + messagingUpdateSMS(messageId: $messageId, topics: $topics, users: $users, targets: $targets, content: $content, status: $status, description: $description, deliveryTime: $deliveryTime) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } }'; case self::$UPDATE_PUSH_NOTIFICATION: - return 'mutation updatePushNotification($messageId: String!, $to: [String!], $title: String, $body: String, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $description: String, $deliveryTime: String) { - messagingUpdatePushNotification(messageId: $messageId, to: $to, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, description: $description, deliveryTime: $deliveryTime) { + return 'mutation updatePushNotification($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $title: String, $body: String, $data: Json, $action: String, $icon: String, $sound: String, $color: String, $tag: String, $badge: String, $status: String, $description: String, $deliveryTime: String) { + messagingUpdatePushNotification(messageId: $messageId, topics: $topics, users: $users, targets: $targets, title: $title, body: $body, data: $data, action: $action, icon: $icon, sound: $sound, color: $color, tag: $tag, badge: $badge, status: $status, description: $description, deliveryTime: $deliveryTime) { _id - to + topics + users + targets deliveryTime deliveredAt deliveryErrors - deliveredTo + deliveredTotal status description } diff --git a/tests/e2e/Services/GraphQL/MessagingTest.php b/tests/e2e/Services/GraphQL/MessagingTest.php index 82f697f7ec..004f7b2ec0 100644 --- a/tests/e2e/Services/GraphQL/MessagingTest.php +++ b/tests/e2e/Services/GraphQL/MessagingTest.php @@ -631,7 +631,7 @@ class MessagingTest extends Scope 'query' => $query, 'variables' => [ 'messageId' => ID::unique(), - 'to' => [$topic['body']['data']['messagingCreateTopic']['_id']], + 'topics' => [$topic['body']['data']['messagingCreateTopic']['_id']], 'subject' => 'Khali beats Undertaker', 'content' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', ], @@ -660,7 +660,7 @@ class MessagingTest extends Scope ]), $graphQLPayload); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTo']); + $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['data']['messagingGetMessage']['deliveryErrors'])); return $message['body']['data']['messagingGetMessage']; @@ -777,7 +777,7 @@ class MessagingTest extends Scope 'variables' => [ 'messageId' => ID::unique(), 'status' => 'draft', - 'to' => [$topic['body']['data']['messagingCreateTopic']['_id']], + 'topics' => [$topic['body']['data']['messagingCreateTopic']['_id']], 'subject' => 'Khali beats Undertaker', 'content' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', ], @@ -822,7 +822,7 @@ class MessagingTest extends Scope ]), $graphQLPayload); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTo']); + $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['data']['messagingGetMessage']['deliveryErrors'])); } @@ -931,7 +931,7 @@ class MessagingTest extends Scope 'query' => $query, 'variables' => [ 'messageId' => ID::unique(), - 'to' => [$topic['body']['data']['messagingCreateTopic']['_id']], + 'topics' => [$topic['body']['data']['messagingCreateTopic']['_id']], 'content' => '454665', ], ]; @@ -959,7 +959,7 @@ class MessagingTest extends Scope ]), $graphQLPayload); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTo']); + $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['data']['messagingGetMessage']['deliveryErrors'])); return $message['body']['data']['messagingGetMessage']; } @@ -1073,7 +1073,7 @@ class MessagingTest extends Scope 'variables' => [ 'messageId' => ID::unique(), 'status' => 'draft', - 'to' => [$topic['body']['data']['messagingCreateTopic']['_id']], + 'topics' => [$topic['body']['data']['messagingCreateTopic']['_id']], 'content' => '345463', ], ]; @@ -1117,7 +1117,7 @@ class MessagingTest extends Scope ]), $graphQLPayload); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTo']); + $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['data']['messagingGetMessage']['deliveryErrors'])); } @@ -1222,7 +1222,7 @@ class MessagingTest extends Scope 'query' => $query, 'variables' => [ 'messageId' => ID::unique(), - 'to' => [$topic['body']['data']['messagingCreateTopic']['_id']], + 'topics' => [$topic['body']['data']['messagingCreateTopic']['_id']], 'title' => 'Push Notification Title', 'body' => 'Push Notifiaction Body', ], @@ -1251,7 +1251,7 @@ class MessagingTest extends Scope ]), $graphQLPayload); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTo']); + $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['data']['messagingGetMessage']['deliveryErrors'])); return $message['body']['data']['messagingGetMessage']; @@ -1361,7 +1361,7 @@ class MessagingTest extends Scope 'variables' => [ 'messageId' => ID::unique(), 'status' => 'draft', - 'to' => [$topic['body']['data']['messagingCreateTopic']['_id']], + 'topics' => [$topic['body']['data']['messagingCreateTopic']['_id']], 'title' => 'Push Notification Title', 'body' => 'Push Notifiaction Body', ], @@ -1406,7 +1406,7 @@ class MessagingTest extends Scope ]), $graphQLPayload); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTo']); + $this->assertEquals(1, $message['body']['data']['messagingGetMessage']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['data']['messagingGetMessage']['deliveryErrors'])); } } diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 01138c6412..b3a075d579 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -486,7 +486,7 @@ trait MessagingBase 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'messageId' => ID::unique(), - 'to' => [$topic['body']['$id']], + 'topics' => [$topic['body']['$id']], 'subject' => 'Khali beats Undertaker', 'content' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', ]); @@ -503,7 +503,7 @@ trait MessagingBase ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); return $message; @@ -605,7 +605,7 @@ trait MessagingBase ], [ 'messageId' => ID::unique(), 'status' => 'draft', - 'to' => [$topic['body']['$id']], + 'topics' => [$topic['body']['$id']], 'subject' => 'Khali beats Undertaker', 'content' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', ]); @@ -632,7 +632,7 @@ trait MessagingBase ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); } @@ -717,7 +717,7 @@ trait MessagingBase 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'messageId' => ID::unique(), - 'to' => [$topic['body']['$id']], + 'topics' => [$topic['body']['$id']], 'content' => '064763', ]); @@ -733,7 +733,7 @@ trait MessagingBase ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); return $message; @@ -833,7 +833,7 @@ trait MessagingBase ], [ 'messageId' => ID::unique(), 'status' => 'draft', - 'to' => [$topic['body']['$id']], + 'topics' => [$topic['body']['$id']], 'content' => '047487', ]); @@ -859,7 +859,7 @@ trait MessagingBase ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); } @@ -940,7 +940,7 @@ trait MessagingBase 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'messageId' => ID::unique(), - 'to' => [$topic['body']['$id']], + 'topics' => [$topic['body']['$id']], 'title' => 'Test-Notification', 'body' => 'Test-Notification-Body', ]); @@ -957,7 +957,7 @@ trait MessagingBase ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); return $message; @@ -1053,7 +1053,7 @@ trait MessagingBase ], [ 'messageId' => ID::unique(), 'status' => 'draft', - 'to' => [$topic['body']['$id']], + 'topics' => [$topic['body']['$id']], 'title' => 'Test-Notification', 'body' => 'Test-Notification-Body', ]); @@ -1080,7 +1080,7 @@ trait MessagingBase ]); $this->assertEquals(200, $message['headers']['status-code']); - $this->assertEquals(1, $message['body']['deliveredTo']); + $this->assertEquals(1, $message['body']['deliveredTotal']); $this->assertEquals(0, \count($message['body']['deliveryErrors'])); } } From a01d361886d728b5e985e8cdd6c5e53546d1e024 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 31 Oct 2023 01:12:31 +0530 Subject: [PATCH 2/7] review changes --- app/config/collections.php | 2 +- app/controllers/api/messaging.php | 13 +++++++++++++ tests/e2e/Services/Messaging/MessagingBase.php | 4 +++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index cf21df2ebf..33a60fce44 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1728,7 +1728,7 @@ $commonCollections = [ [ '$id' => ID::custom('_key_search'), 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], + 'attributes' => ['search'], 'lengths' => [], 'orders' => [Database::ORDER_ASC], ] diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 567c8e2cd6..0147e472bb 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1400,6 +1400,9 @@ App::post('/v1/messaging/topics') if ($description) { $topic->setAttribute('description', $description); + $topic->setAttribute('search', $topic->getId() . ' ' . $name . ' ' . $description); + } else { + $topic->setAttribute('search', $topic->getId() . ' ' . $name); } try { @@ -1516,6 +1519,16 @@ App::patch('/v1/messaging/topics/:topicId') $topic->setAttribute('description', $description); } + if (!empty($name) || !empty($description)) { + if (!empty($name) && !empty($description)) { + $topic->setAttribute('search', $topic->getId() . ' ' . $name . ' ' . $description); + } elseif (!empty($name)) { + $topic->setAttribute('search', $topic->getId() . ' ' . $name . ' ' . $topic->getAttribute('description')); + } else { + $topic->setAttribute('search', $topic->getId() . ' ' . $topic->getAttribute('name') . ' ' . $description); + } + } + $topic = $dbForProject->updateDocument('topics', $topicId, $topic); $response diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index b3a075d579..65e196db30 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -223,7 +223,7 @@ trait MessagingBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ - 'topicId' => 'unique()', + 'topicId' => ID::unique(), 'name' => 'my-app', 'description' => 'web app' ]); @@ -258,6 +258,8 @@ trait MessagingBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'search' => 'updated-description', ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(1, \count($response['body']['topics'])); From 0dafc59cc2c2c127081e8fad7da8375fc7fd71a9 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 31 Oct 2023 02:05:50 +0530 Subject: [PATCH 3/7] converted env vars to dsn format --- .env | 14 +---- docker-compose.yml | 14 +---- .../Account/AccountCustomClientTest.php | 10 ++-- tests/e2e/Services/GraphQL/AccountTest.php | 10 ++-- tests/e2e/Services/GraphQL/MessagingTest.php | 57 ++++++++++++------- .../e2e/Services/Messaging/MessagingBase.php | 57 ++++++++++++------- 6 files changed, 88 insertions(+), 74 deletions(-) diff --git a/.env b/.env index 127efd2e4a..07d953af57 100644 --- a/.env +++ b/.env @@ -99,14 +99,6 @@ _APP_VCS_GITHUB_WEBHOOK_SECRET= _APP_MIGRATIONS_FIREBASE_CLIENT_ID= _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET= _APP_ASSISTANT_OPENAI_API_KEY= -_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID= -_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY= -_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM= -_APP_MESSAGE_SMS_PROVIDER_MSG91_TO= -_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_API_KEY= -_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_DOMAIN= -_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_FROM= -_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_RECEIVER_EMAIL= -_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_IS_EU_REGION= -_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY= -_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN= +_APP_MESSAGE_SMS_TEST_DSN= +_APP_MESSAGE_EMAIL_TEST_DSN= +_APP_MESSAGE_PUSH_TEST_DSN= diff --git a/docker-compose.yml b/docker-compose.yml index c0013f7385..94e8a8bd7c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -188,17 +188,9 @@ services: - _APP_MIGRATIONS_FIREBASE_CLIENT_ID - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET - _APP_ASSISTANT_OPENAI_API_KEY - - _APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID - - _APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY - - _APP_MESSAGE_SMS_PROVIDER_MSG91_FROM - - _APP_MESSAGE_SMS_PROVIDER_MSG91_TO - - _APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_API_KEY - - _APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_DOMAIN - - _APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_FROM - - _APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_RECEIVER_EMAIL - - _APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_IS_EU_REGION - - _APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY - - _APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN + - _APP_MESSAGE_SMS_TEST_DSN + - _APP_MESSAGE_EMAIL_TEST_DSN + - _APP_MESSAGE_PUSH_TEST_DSN appwrite-realtime: entrypoint: realtime <<: *x-logging diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index c138f4049a..1e716fc634 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -11,6 +11,7 @@ use Utopia\App; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Datetime as DatetimeValidator; +use Utopia\DSN\DSN; use function sleep; @@ -743,10 +744,11 @@ class AccountCustomClientTest extends Scope public function testCreatePhone(): array { - $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); - $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); - $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); - $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $to = $smsDSN->getParam('to'); + $from = $smsDSN->getParam('from'); + $authKey = $smsDSN->getPassword(); + $senderId = $smsDSN->getUser(); if (empty($to) || empty($from) || empty($authKey) || empty($senderId)) { $this->markTestSkipped('SMS provider not configured'); diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index e42fe1bc6c..292d7d7db4 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\App; use Utopia\Database\Helpers\ID; +use Utopia\DSN\DSN; class AccountTest extends Scope { @@ -123,10 +124,11 @@ class AccountTest extends Scope */ public function testCreatePhoneVerification(): array { - $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); - $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); - $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); - $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $to = $smsDSN->getParam('to'); + $from = $smsDSN->getParam('from'); + $authKey = $smsDSN->getPassword(); + $senderId = $smsDSN->getUser(); if (empty($to) || empty($from) || empty($authKey) || empty($senderId)) { $this->markTestSkipped('SMS provider not configured'); diff --git a/tests/e2e/Services/GraphQL/MessagingTest.php b/tests/e2e/Services/GraphQL/MessagingTest.php index 004f7b2ec0..892fb51dce 100644 --- a/tests/e2e/Services/GraphQL/MessagingTest.php +++ b/tests/e2e/Services/GraphQL/MessagingTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\App; use Utopia\Database\Helpers\ID; +use Utopia\DSN\DSN; class MessagingTest extends Scope { @@ -526,11 +527,13 @@ class MessagingTest extends Scope public function testSendEmail() { - $to = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_RECEIVER_EMAIL'); - $from = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_FROM'); - $apiKey = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_API_KEY'); - $domain = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_DOMAIN'); - $isEuRegion = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_IS_EU_REGION'); + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); + $to = $emailDSN->getParam('to'); + $from = $emailDSN->getParam('from'); + $isEuRegion = $emailDSN->getParam('isEuRegion'); + $apiKey = $emailDSN->getPassword(); + $domain = $emailDSN->getUser(); + if (empty($to) || empty($from) || empty($apiKey) || empty($domain) || empty($isEuRegion)) { $this->markTestSkipped('Email provider not configured'); } @@ -671,11 +674,13 @@ class MessagingTest extends Scope */ public function testUpdateEmail(array $email) { - $to = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_RECEIVER_EMAIL'); - $from = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_FROM'); - $apiKey = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_API_KEY'); - $domain = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_DOMAIN'); - $isEuRegion = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_IS_EU_REGION'); + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); + $to = $emailDSN->getParam('to'); + $from = $emailDSN->getParam('from'); + $isEuRegion = $emailDSN->getParam('isEuRegion'); + $apiKey = $emailDSN->getPassword(); + $domain = $emailDSN->getUser(); + if (empty($to) || empty($from) || empty($apiKey) || empty($domain) || empty($isEuRegion)) { $this->markTestSkipped('Email provider not configured'); } @@ -828,10 +833,12 @@ class MessagingTest extends Scope public function testSendSMS() { - $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); - $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); - $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $to = $smsDSN->getParam('to'); + $from = $smsDSN->getParam('from'); + $authKey = $smsDSN->getPassword(); + $senderId = $smsDSN->getUser(); + if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) { $this->markTestSkipped('SMS provider not configured'); } @@ -969,10 +976,12 @@ class MessagingTest extends Scope */ public function testUpdateSMS(array $sms) { - $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); - $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); - $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $to = $smsDSN->getParam('to'); + $from = $smsDSN->getParam('from'); + $authKey = $smsDSN->getPassword(); + $senderId = $smsDSN->getUser(); + if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) { $this->markTestSkipped('SMS provider not configured'); } @@ -1123,8 +1132,10 @@ class MessagingTest extends Scope public function testSendPushNotification() { - $to = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN'); - $serverKey = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY'); + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); + $to = $pushDSN->getParam('to'); + $serverKey = $pushDSN->getPassword(); + if (empty($to) || empty($serverKey)) { $this->markTestSkipped('Push provider not configured'); } @@ -1262,8 +1273,10 @@ class MessagingTest extends Scope */ public function testUpdatePushNotification(array $push) { - $to = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN'); - $serverKey = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY'); + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); + $to = $pushDSN->getParam('to'); + $serverKey = $pushDSN->getPassword(); + if (empty($to) || empty($serverKey)) { $this->markTestSkipped('Push provider not configured'); } diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 65e196db30..720de96052 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Messaging; use Tests\E2E\Client; use Utopia\App; use Utopia\Database\Helpers\ID; +use Utopia\DSN\DSN; trait MessagingBase { @@ -407,11 +408,13 @@ trait MessagingBase public function testSendEmail() { - $to = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_RECEIVER_EMAIL'); - $from = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_FROM'); - $apiKey = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_API_KEY'); - $domain = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_DOMAIN'); - $isEuRegion = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_IS_EU_REGION'); + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); + $to = $emailDSN->getParam('to'); + $from = $emailDSN->getParam('from'); + $isEuRegion = $emailDSN->getParam('isEuRegion'); + $apiKey = $emailDSN->getPassword(); + $domain = $emailDSN->getUser(); + if (empty($to) || empty($from) || empty($apiKey) || empty($domain) || empty($isEuRegion)) { $this->markTestSkipped('Email provider not configured'); } @@ -516,11 +519,13 @@ trait MessagingBase */ public function testUpdateEmail(array $email) { - $to = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_RECEIVER_EMAIL'); - $from = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_FROM'); - $apiKey = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_API_KEY'); - $domain = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_DOMAIN'); - $isEuRegion = App::getEnv('_APP_MESSAGE_EMAIL_PROVIDER_MAILGUN_IS_EU_REGION'); + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); + $to = $emailDSN->getParam('to'); + $from = $emailDSN->getParam('from'); + $isEuRegion = $emailDSN->getParam('isEuRegion'); + $apiKey = $emailDSN->getPassword(); + $domain = $emailDSN->getUser(); + if (empty($to) || empty($from) || empty($apiKey) || empty($domain) || empty($isEuRegion)) { $this->markTestSkipped('Email provider not configured'); } @@ -640,10 +645,12 @@ trait MessagingBase public function testSendSMS() { - $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); - $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); - $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $to = $smsDSN->getParam('to'); + $from = $smsDSN->getParam('from'); + $authKey = $smsDSN->getPassword(); + $senderId = $smsDSN->getUser(); + if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) { $this->markTestSkipped('SMS provider not configured'); } @@ -746,10 +753,12 @@ trait MessagingBase */ public function testUpdateSMS(array $sms) { - $to = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_TO'); - $from = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM'); - $senderId = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_SENDER_ID'); - $authKey = App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_AUTH_KEY'); + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $to = $smsDSN->getParam('to'); + $from = $smsDSN->getParam('from'); + $authKey = $smsDSN->getPassword(); + $senderId = $smsDSN->getUser(); + if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) { $this->markTestSkipped('SMS provider not configured'); } @@ -867,8 +876,10 @@ trait MessagingBase public function testSendPushNotification() { - $to = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN'); - $serverKey = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY'); + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); + $to = $pushDSN->getParam('to'); + $serverKey = $pushDSN->getPassword(); + if (empty($to) || empty($serverKey)) { $this->markTestSkipped('Push provider not configured'); } @@ -970,8 +981,10 @@ trait MessagingBase */ public function testUpdatePushNotification(array $push) { - $to = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN'); - $serverKey = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY'); + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); + $to = $pushDSN->getParam('to'); + $serverKey = $pushDSN->getPassword(); + if (empty($to) || empty($serverKey)) { $this->markTestSkipped('Push provider not configured'); } From a4c8d852a5c21aad931275e0d304cb599e8a5d65 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 31 Oct 2023 02:34:18 +0530 Subject: [PATCH 4/7] adds test skip condition if dsn not provided --- .../Account/AccountCustomClientTest.php | 4 ++++ tests/e2e/Services/GraphQL/AccountTest.php | 4 ++++ tests/e2e/Services/GraphQL/MessagingTest.php | 24 +++++++++++++++++++ .../e2e/Services/Messaging/MessagingBase.php | 24 +++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 1e716fc634..336d6f317c 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -744,6 +744,10 @@ class AccountCustomClientTest extends Scope public function testCreatePhone(): array { + if (empty(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'))) { + $this->markTestSkipped('SMS DSN not provided'); + } + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); $to = $smsDSN->getParam('to'); $from = $smsDSN->getParam('from'); diff --git a/tests/e2e/Services/GraphQL/AccountTest.php b/tests/e2e/Services/GraphQL/AccountTest.php index 292d7d7db4..9d1da09feb 100644 --- a/tests/e2e/Services/GraphQL/AccountTest.php +++ b/tests/e2e/Services/GraphQL/AccountTest.php @@ -124,6 +124,10 @@ class AccountTest extends Scope */ public function testCreatePhoneVerification(): array { + if (empty(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'))) { + $this->markTestSkipped('SMS DSN not provided'); + } + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); $to = $smsDSN->getParam('to'); $from = $smsDSN->getParam('from'); diff --git a/tests/e2e/Services/GraphQL/MessagingTest.php b/tests/e2e/Services/GraphQL/MessagingTest.php index 892fb51dce..c0322372ba 100644 --- a/tests/e2e/Services/GraphQL/MessagingTest.php +++ b/tests/e2e/Services/GraphQL/MessagingTest.php @@ -527,6 +527,10 @@ class MessagingTest extends Scope public function testSendEmail() { + if (empty(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'))) { + $this->markTestSkipped('Email DSN not provided'); + } + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); $to = $emailDSN->getParam('to'); $from = $emailDSN->getParam('from'); @@ -674,6 +678,10 @@ class MessagingTest extends Scope */ public function testUpdateEmail(array $email) { + if (empty(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'))) { + $this->markTestSkipped('Email DSN not provided'); + } + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); $to = $emailDSN->getParam('to'); $from = $emailDSN->getParam('from'); @@ -833,6 +841,10 @@ class MessagingTest extends Scope public function testSendSMS() { + if (empty(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'))) { + $this->markTestSkipped('SMS DSN not provided'); + } + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); $to = $smsDSN->getParam('to'); $from = $smsDSN->getParam('from'); @@ -976,6 +988,10 @@ class MessagingTest extends Scope */ public function testUpdateSMS(array $sms) { + if (empty(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'))) { + $this->markTestSkipped('SMS DSN not provided'); + } + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); $to = $smsDSN->getParam('to'); $from = $smsDSN->getParam('from'); @@ -1132,6 +1148,10 @@ class MessagingTest extends Scope public function testSendPushNotification() { + if (empty(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'))) { + $this->markTestSkipped('Push DSN empty'); + } + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); $to = $pushDSN->getParam('to'); $serverKey = $pushDSN->getPassword(); @@ -1273,6 +1293,10 @@ class MessagingTest extends Scope */ public function testUpdatePushNotification(array $push) { + if (empty(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'))) { + $this->markTestSkipped('Push DSN empty'); + } + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); $to = $pushDSN->getParam('to'); $serverKey = $pushDSN->getPassword(); diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 720de96052..221617a1d1 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -408,6 +408,10 @@ trait MessagingBase public function testSendEmail() { + if (empty(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'))) { + $this->markTestSkipped('Email DSN not provided'); + } + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); $to = $emailDSN->getParam('to'); $from = $emailDSN->getParam('from'); @@ -519,6 +523,10 @@ trait MessagingBase */ public function testUpdateEmail(array $email) { + if (empty(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'))) { + $this->markTestSkipped('Email DSN not provided'); + } + $emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN')); $to = $emailDSN->getParam('to'); $from = $emailDSN->getParam('from'); @@ -645,6 +653,10 @@ trait MessagingBase public function testSendSMS() { + if (empty(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'))) { + $this->markTestSkipped('SMS DSN not provided'); + } + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); $to = $smsDSN->getParam('to'); $from = $smsDSN->getParam('from'); @@ -753,6 +765,10 @@ trait MessagingBase */ public function testUpdateSMS(array $sms) { + if (empty(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'))) { + $this->markTestSkipped('SMS DSN not provided'); + } + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); $to = $smsDSN->getParam('to'); $from = $smsDSN->getParam('from'); @@ -876,6 +892,10 @@ trait MessagingBase public function testSendPushNotification() { + if (empty(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'))) { + $this->markTestSkipped('Push DSN empty'); + } + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); $to = $pushDSN->getParam('to'); $serverKey = $pushDSN->getPassword(); @@ -981,6 +1001,10 @@ trait MessagingBase */ public function testUpdatePushNotification(array $push) { + if (empty(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'))) { + $this->markTestSkipped('Push DSN empty'); + } + $pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN')); $to = $pushDSN->getParam('to'); $serverKey = $pushDSN->getPassword(); From a58f473b29b7d86a1bdaa3eab0fac6ca851d63d1 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Tue, 31 Oct 2023 14:01:42 +0530 Subject: [PATCH 5/7] adds createdAt and updatedAt in messaging models --- src/Appwrite/Utopia/Response/Model/Message.php | 12 ++++++++++++ src/Appwrite/Utopia/Response/Model/Provider.php | 12 ++++++++++++ src/Appwrite/Utopia/Response/Model/Subscriber.php | 12 ++++++++++++ src/Appwrite/Utopia/Response/Model/Target.php | 12 ++++++++++++ src/Appwrite/Utopia/Response/Model/Topic.php | 12 ++++++++++++ 5 files changed, 60 insertions(+) diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 7816c4bf5d..0341ebdfa0 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -17,6 +17,18 @@ class Message extends Any 'default' => '', 'example' => '5e5ea5c16897e', ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket creation time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ->addRule('topics', [ 'type' => self::TYPE_STRING, 'description' => 'Topic IDs set as recipients.', diff --git a/src/Appwrite/Utopia/Response/Model/Provider.php b/src/Appwrite/Utopia/Response/Model/Provider.php index ba522951e7..3f1e2d6c6b 100644 --- a/src/Appwrite/Utopia/Response/Model/Provider.php +++ b/src/Appwrite/Utopia/Response/Model/Provider.php @@ -16,6 +16,18 @@ class Provider extends Model 'default' => '', 'example' => '5e5ea5c16897e', ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket creation time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ->addRule('name', [ 'type' => self::TYPE_STRING, 'description' => 'The name for the provider instance.', diff --git a/src/Appwrite/Utopia/Response/Model/Subscriber.php b/src/Appwrite/Utopia/Response/Model/Subscriber.php index 2f34619cb4..68bb4ef180 100644 --- a/src/Appwrite/Utopia/Response/Model/Subscriber.php +++ b/src/Appwrite/Utopia/Response/Model/Subscriber.php @@ -16,6 +16,18 @@ class Subscriber extends Model 'default' => '', 'example' => '259125845563242502', ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket creation time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ->addRule('targetId', [ 'type' => self::TYPE_STRING, 'description' => 'Target ID.', diff --git a/src/Appwrite/Utopia/Response/Model/Target.php b/src/Appwrite/Utopia/Response/Model/Target.php index 5750f57eba..4547e25e54 100644 --- a/src/Appwrite/Utopia/Response/Model/Target.php +++ b/src/Appwrite/Utopia/Response/Model/Target.php @@ -16,6 +16,18 @@ class Target extends Model 'default' => '', 'example' => '259125845563242502', ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket creation time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ->addRule('userId', [ 'type' => self::TYPE_STRING, 'description' => 'User ID.', diff --git a/src/Appwrite/Utopia/Response/Model/Topic.php b/src/Appwrite/Utopia/Response/Model/Topic.php index d46d26597d..9f8c378576 100644 --- a/src/Appwrite/Utopia/Response/Model/Topic.php +++ b/src/Appwrite/Utopia/Response/Model/Topic.php @@ -16,6 +16,18 @@ class Topic extends Model 'default' => '', 'example' => '259125845563242502', ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket creation time in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Bucket update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ->addRule('name', [ 'type' => self::TYPE_STRING, 'description' => 'The name of the topic.', From 76d7369314e93159b73adf3661ead0fc3103aad1 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 2 Nov 2023 12:20:15 +0530 Subject: [PATCH 6/7] fixes description for messaging service models --- src/Appwrite/Utopia/Response/Model/Message.php | 4 ++-- src/Appwrite/Utopia/Response/Model/Provider.php | 4 ++-- src/Appwrite/Utopia/Response/Model/Subscriber.php | 4 ++-- src/Appwrite/Utopia/Response/Model/Target.php | 4 ++-- src/Appwrite/Utopia/Response/Model/Topic.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Message.php b/src/Appwrite/Utopia/Response/Model/Message.php index 0341ebdfa0..27c70d7073 100644 --- a/src/Appwrite/Utopia/Response/Model/Message.php +++ b/src/Appwrite/Utopia/Response/Model/Message.php @@ -19,13 +19,13 @@ class Message extends Any ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket creation time in ISO 8601 format.', + 'description' => 'Message creation time in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket update date in ISO 8601 format.', + 'description' => 'Message update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) diff --git a/src/Appwrite/Utopia/Response/Model/Provider.php b/src/Appwrite/Utopia/Response/Model/Provider.php index 3f1e2d6c6b..a121753275 100644 --- a/src/Appwrite/Utopia/Response/Model/Provider.php +++ b/src/Appwrite/Utopia/Response/Model/Provider.php @@ -18,13 +18,13 @@ class Provider extends Model ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket creation time in ISO 8601 format.', + 'description' => 'Provider creation time in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket update date in ISO 8601 format.', + 'description' => 'Provider update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) diff --git a/src/Appwrite/Utopia/Response/Model/Subscriber.php b/src/Appwrite/Utopia/Response/Model/Subscriber.php index 68bb4ef180..65bbd38f0e 100644 --- a/src/Appwrite/Utopia/Response/Model/Subscriber.php +++ b/src/Appwrite/Utopia/Response/Model/Subscriber.php @@ -18,13 +18,13 @@ class Subscriber extends Model ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket creation time in ISO 8601 format.', + 'description' => 'Subscriber creation time in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket update date in ISO 8601 format.', + 'description' => 'Subscriber update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) diff --git a/src/Appwrite/Utopia/Response/Model/Target.php b/src/Appwrite/Utopia/Response/Model/Target.php index 4547e25e54..c6c5929ee3 100644 --- a/src/Appwrite/Utopia/Response/Model/Target.php +++ b/src/Appwrite/Utopia/Response/Model/Target.php @@ -18,13 +18,13 @@ class Target extends Model ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket creation time in ISO 8601 format.', + 'description' => 'Target creation time in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket update date in ISO 8601 format.', + 'description' => 'Target update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) diff --git a/src/Appwrite/Utopia/Response/Model/Topic.php b/src/Appwrite/Utopia/Response/Model/Topic.php index 9f8c378576..096ddb347f 100644 --- a/src/Appwrite/Utopia/Response/Model/Topic.php +++ b/src/Appwrite/Utopia/Response/Model/Topic.php @@ -18,13 +18,13 @@ class Topic extends Model ]) ->addRule('$createdAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket creation time in ISO 8601 format.', + 'description' => 'Topic creation time in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('$updatedAt', [ 'type' => self::TYPE_DATETIME, - 'description' => 'Bucket update date in ISO 8601 format.', + 'description' => 'Topic update date in ISO 8601 format.', 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) From 270e6e7c151e10ad05e1237b1d525f8619ca7772 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Thu, 2 Nov 2023 16:43:24 +0530 Subject: [PATCH 7/7] review changes --- app/controllers/api/messaging.php | 42 +++++++++---------- composer.lock | 2 +- docker-compose.yml | 1 + src/Appwrite/Platform/Workers/Messaging.php | 2 +- .../Account/AccountCustomClientTest.php | 4 +- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 0147e472bb..0207708b8b 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2041,9 +2041,9 @@ App::patch('/v1/messaging/messages/email/:messageId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new UID(), 'Message ID.') - ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) - ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) - ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) + ->param('topics', null, new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs.', true) + ->param('users', null, new ArrayList(new Text(Database::LENGTH_KEY)), 'List of User IDs.', true) + ->param('targets', null, new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Targets IDs.', true) ->param('subject', '', new Text(998), 'Email Subject.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(64230), 'Email Content.', true) @@ -2054,7 +2054,7 @@ App::patch('/v1/messaging/messages/email/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $topics, array $users, array $targets, string $subject, string $description, string $content, string $status, bool $html, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, string $subject, string $description, string $content, string $status, bool $html, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -2069,15 +2069,15 @@ App::patch('/v1/messaging/messages/email/:messageId') throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED); } - if (\count($topics) > 0) { + if (!\is_null($topics)) { $message->setAttribute('topics', $topics); } - if (\count($users) > 0) { + if (!\is_null($users)) { $message->setAttribute('users', $users); } - if (\count($targets) > 0) { + if (!\is_null($targets)) { $message->setAttribute('targets', $targets); } @@ -2138,9 +2138,9 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new UID(), 'Message ID.') - ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) - ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) - ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) + ->param('topics', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('content', '', new Text(64230), 'Email Content.', true) ->param('status', '', new WhiteList(['draft', 'processing']), 'Message Status. Value must be either draft or processing.', true) @@ -2149,7 +2149,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $topics, array $users, array $targets, string $description, string $content, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, string $description, string $content, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -2164,15 +2164,15 @@ App::patch('/v1/messaging/messages/sms/:messageId') throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED); } - if (\count($topics) > 0) { + if (!\is_null($topics)) { $message->setAttribute('topics', $topics); } - if (\count($users) > 0) { + if (!\is_null($users)) { $message->setAttribute('users', $users); } - if (\count($targets) > 0) { + if (!\is_null($targets)) { $message->setAttribute('targets', $targets); } @@ -2225,9 +2225,9 @@ App::patch('/v1/messaging/messages/push/:messageId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MESSAGE) ->param('messageId', '', new UID(), 'Message ID.') - ->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) - ->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) - ->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) + ->param('topics', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true) + ->param('users', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true) + ->param('targets', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true) ->param('description', '', new Text(256), 'Description for Message.', true) ->param('title', '', new Text(256), 'Title for push notification.', true) ->param('body', '', new Text(64230), 'Body for push notification.', true) @@ -2243,7 +2243,7 @@ App::patch('/v1/messaging/messages/push/:messageId') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, array $topics, array $users, array $targets, string $description, string $title, string $body, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, string $description, string $title, string $body, ?array $data, string $action, string $icon, string $sound, string $color, string $tag, string $badge, string $status, ?string $deliveryTime, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -2258,15 +2258,15 @@ App::patch('/v1/messaging/messages/push/:messageId') throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED); } - if (\count($topics) > 0) { + if (!\is_null($topics)) { $message->setAttribute('topics', $topics); } - if (\count($users) > 0) { + if (!\is_null($users)) { $message->setAttribute('users', $users); } - if (\count($targets) > 0) { + if (!\is_null($targets)) { $message->setAttribute('targets', $targets); } diff --git a/composer.lock b/composer.lock index 560dfe7b20..66e5e5a11b 100644 --- a/composer.lock +++ b/composer.lock @@ -5822,5 +5822,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/docker-compose.yml b/docker-compose.yml index 94e8a8bd7c..8255508356 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -570,6 +570,7 @@ services: environment: - _APP_ENV - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST - _APP_REDIS_PORT - _APP_REDIS_USER diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index a56c98b5e5..63e0ff651a 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -113,7 +113,7 @@ class Messaging extends Action */ $results = batch(\array_map(function ($providerId) use ($providers, $message, $dbForProject) { return function () use ($providerId, $providers, $message, $dbForProject) { - $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); + $provider = $dbForProject->getDocument('providers', $providerId); $identifiers = $providers[$providerId]; $adapter = match ($provider->getAttribute('type')) { 'sms' => $this->sms($provider), diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 336d6f317c..d56f93a42c 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -1018,6 +1018,8 @@ class AccountCustomClientTest extends Scope public function testPhoneVerification(array $data): array { $session = $data['session'] ?? ''; + $smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN')); + $from = $smsDSN->getParam('from'); /** * Test for SUCCESS @@ -1028,7 +1030,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), ['from' => App::getEnv('_APP_MESSAGE_SMS_PROVIDER_MSG91_FROM')]); + ]), ['from' => $from]); $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']);