Merge pull request #7048 from appwrite/1.5.x_review_changes

review changes
This commit is contained in:
Jake Barnby 2023-11-09 19:47:09 +13:00 committed by GitHub
commit a9c7b640ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 644 additions and 249 deletions

14
.env
View file

@ -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=

View file

@ -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,
@ -1706,7 +1728,7 @@ $commonCollections = [
[
'$id' => ID::custom('_key_search'),
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['name'],
'attributes' => ['search'],
'lengths' => [],
'orders' => [Database::ORDER_ASC],
]

View file

@ -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.',

View file

@ -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,
],

View file

@ -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);
});
@ -1274,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 {
@ -1390,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
@ -1620,9 +1759,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 +1772,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 +1820,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 +1831,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 +1877,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 +1896,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 +1938,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 +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('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', 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)
@ -1889,7 +2054,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 +2069,16 @@ App::patch('/v1/messaging/messages/email/:messageId')
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
}
if (\count($to) > 0) {
$message->setAttribute('to', $to);
if (!\is_null($topics)) {
$message->setAttribute('topics', $topics);
}
if (!\is_null($users)) {
$message->setAttribute('users', $users);
}
if (!\is_null($targets)) {
$message->setAttribute('targets', $targets);
}
$data = $message->getAttribute('data');
@ -1965,7 +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('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', 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)
@ -1974,7 +2149,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 +2164,16 @@ App::patch('/v1/messaging/messages/sms/:messageId')
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
}
if (\count($to) > 0) {
$message->setAttribute('to', $to);
if (!\is_null($topics)) {
$message->setAttribute('topics', $topics);
}
if (!\is_null($users)) {
$message->setAttribute('users', $users);
}
if (!\is_null($targets)) {
$message->setAttribute('targets', $targets);
}
$data = $message->getAttribute('data');
@ -2042,7 +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('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', 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)
@ -2058,7 +2243,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 +2258,16 @@ App::patch('/v1/messaging/messages/push/:messageId')
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
}
if (\count($to) > 0) {
$message->setAttribute('to', $to);
if (!\is_null($topics)) {
$message->setAttribute('topics', $topics);
}
if (!\is_null($users)) {
$message->setAttribute('users', $users);
}
if (!\is_null($targets)) {
$message->setAttribute('targets', $targets);
}
$pushData = $message->getAttribute('data');

View file

@ -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,
],

View file

@ -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
@ -578,6 +570,7 @@ services:
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER

View file

@ -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';

View file

@ -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) {
@ -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);

View file

@ -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',

View file

@ -8,7 +8,7 @@ class Providers extends Base
'name',
'provider',
'type',
'default',
'internal',
'enabled',
];

View file

@ -17,12 +17,38 @@ class Message extends Any
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('to', [
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Message creation time in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Message update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->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 +72,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,

View file

@ -16,6 +16,18 @@ class Provider extends Model
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Provider creation time in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Provider 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.',
@ -28,7 +40,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,

View file

@ -16,6 +16,18 @@ class Subscriber extends Model
'default' => '',
'example' => '259125845563242502',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Subscriber creation time in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Subscriber update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('targetId', [
'type' => self::TYPE_STRING,
'description' => 'Target ID.',

View file

@ -16,6 +16,18 @@ class Target extends Model
'default' => '',
'example' => '259125845563242502',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Target creation time in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Target update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('userId', [
'type' => self::TYPE_STRING,
'description' => 'User ID.',

View file

@ -16,6 +16,18 @@ class Topic extends Model
'default' => '',
'example' => '259125845563242502',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Topic creation time in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Topic update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('name', [
'type' => self::TYPE_STRING,
'description' => 'The name of the topic.',

View file

@ -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,15 @@ 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');
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');
$authKey = $smsDSN->getPassword();
$senderId = $smsDSN->getUser();
if (empty($to) || empty($from) || empty($authKey) || empty($senderId)) {
$this->markTestSkipped('SMS provider not configured');
@ -762,7 +768,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 +815,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']));
@ -1013,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
@ -1023,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']);
@ -1040,7 +1047,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, [

View file

@ -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,15 @@ 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');
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');
$authKey = $smsDSN->getPassword();
$senderId = $smsDSN->getUser();
if (empty($to) || empty($from) || empty($authKey) || empty($senderId)) {
$this->markTestSkipped('SMS provider not configured');
@ -142,7 +148,6 @@ class AccountTest extends Scope
'from' => $from,
'senderId' => $senderId,
'authKey' => $authKey,
'default' => true,
],
];

View file

@ -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
}

View file

@ -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,17 @@ 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');
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');
$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');
}
@ -631,7 +638,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 +667,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'];
@ -671,11 +678,17 @@ 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');
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');
$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');
}
@ -777,7 +790,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,16 +835,22 @@ 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']));
}
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');
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');
$authKey = $smsDSN->getPassword();
$senderId = $smsDSN->getUser();
if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) {
$this->markTestSkipped('SMS provider not configured');
}
@ -931,7 +950,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 +978,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'];
}
@ -969,10 +988,16 @@ 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');
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');
$authKey = $smsDSN->getPassword();
$senderId = $smsDSN->getUser();
if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) {
$this->markTestSkipped('SMS provider not configured');
}
@ -1073,7 +1098,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,14 +1142,20 @@ 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']));
}
public function testSendPushNotification()
{
$to = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN');
$serverKey = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY');
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();
if (empty($to) || empty($serverKey)) {
$this->markTestSkipped('Push provider not configured');
}
@ -1222,7 +1253,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 +1282,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'];
@ -1262,8 +1293,14 @@ 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');
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();
if (empty($to) || empty($serverKey)) {
$this->markTestSkipped('Push provider not configured');
}
@ -1361,7 +1398,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 +1443,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']));
}
}

View file

@ -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
{
@ -223,7 +224,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 +259,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']));
@ -405,11 +408,17 @@ 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');
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');
$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');
}
@ -486,7 +495,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 +512,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;
@ -514,11 +523,17 @@ 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');
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');
$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');
}
@ -605,7 +620,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,16 +647,22 @@ 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']));
}
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');
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');
$authKey = $smsDSN->getPassword();
$senderId = $smsDSN->getUser();
if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) {
$this->markTestSkipped('SMS provider not configured');
}
@ -717,7 +738,7 @@ trait MessagingBase
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'messageId' => ID::unique(),
'to' => [$topic['body']['$id']],
'topics' => [$topic['body']['$id']],
'content' => '064763',
]);
@ -733,7 +754,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;
@ -744,10 +765,16 @@ 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');
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');
$authKey = $smsDSN->getPassword();
$senderId = $smsDSN->getUser();
if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) {
$this->markTestSkipped('SMS provider not configured');
}
@ -833,7 +860,7 @@ trait MessagingBase
], [
'messageId' => ID::unique(),
'status' => 'draft',
'to' => [$topic['body']['$id']],
'topics' => [$topic['body']['$id']],
'content' => '047487',
]);
@ -859,14 +886,20 @@ 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']));
}
public function testSendPushNotification()
{
$to = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_RECEIVER_TOKEN');
$serverKey = App::getEnv('_APP_MESSAGE_PUSH_PROVIDER_FCM_SERVERY_KEY');
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();
if (empty($to) || empty($serverKey)) {
$this->markTestSkipped('Push provider not configured');
}
@ -940,7 +973,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 +990,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;
@ -968,8 +1001,14 @@ 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');
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();
if (empty($to) || empty($serverKey)) {
$this->markTestSkipped('Push provider not configured');
}
@ -1053,7 +1092,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 +1119,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']));
}
}