Resolve merge conflicts
This commit is contained in:
commit
b74c7671e8
17 changed files with 535 additions and 301 deletions
30
.github/workflows/tests.yml
vendored
30
.github/workflows/tests.yml
vendored
|
@ -75,8 +75,32 @@ jobs:
|
||||||
- name: Run Unit Tests
|
- name: Run Unit Tests
|
||||||
run: docker compose exec appwrite test /usr/src/code/tests/unit
|
run: docker compose exec appwrite test /usr/src/code/tests/unit
|
||||||
|
|
||||||
e2e_test:
|
e2e_general_test:
|
||||||
name: E2E Test
|
name: E2E General Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Load Cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
key: ${{ env.CACHE_KEY }}
|
||||||
|
path: /tmp/${{ env.IMAGE }}.tar
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
|
- name: Load and Start Appwrite
|
||||||
|
run: |
|
||||||
|
docker load --input /tmp/${{ env.IMAGE }}.tar
|
||||||
|
docker compose up -d
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
- name: Run General Tests
|
||||||
|
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/General --debug
|
||||||
|
|
||||||
|
e2e_service_test:
|
||||||
|
name: E2E Service Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: setup
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
|
@ -120,4 +144,4 @@ jobs:
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
- name: Run ${{matrix.service}} Tests
|
- name: Run ${{matrix.service}} Tests
|
||||||
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug
|
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug
|
||||||
|
|
|
@ -876,7 +876,7 @@ App::get('/v1/account/identities')
|
||||||
});
|
});
|
||||||
|
|
||||||
App::delete('/v1/account/identities/:identityId')
|
App::delete('/v1/account/identities/:identityId')
|
||||||
->desc('Delete Identity')
|
->desc('Delete identity')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('event', 'users.[userId].identities.[identityId].delete')
|
->label('event', 'users.[userId].identities.[identityId].delete')
|
||||||
|
@ -893,7 +893,8 @@ App::delete('/v1/account/identities/:identityId')
|
||||||
->param('identityId', '', new UID(), 'Identity ID.')
|
->param('identityId', '', new UID(), 'Identity ID.')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->action(function (string $identityId, Response $response, Database $dbForProject) {
|
->inject('queueForEvents')
|
||||||
|
->action(function (string $identityId, Response $response, Database $dbForProject, Event $queueForEvents) {
|
||||||
|
|
||||||
$identity = $dbForProject->getDocument('identities', $identityId);
|
$identity = $dbForProject->getDocument('identities', $identityId);
|
||||||
|
|
||||||
|
@ -903,6 +904,11 @@ App::delete('/v1/account/identities/:identityId')
|
||||||
|
|
||||||
$dbForProject->deleteDocument('identities', $identityId);
|
$dbForProject->deleteDocument('identities', $identityId);
|
||||||
|
|
||||||
|
$queueForEvents
|
||||||
|
->setParam('userId', $identity->getAttribute('userId'))
|
||||||
|
->setParam('identityId', $identity->getId())
|
||||||
|
->setPayload($response->output($identity, Response::MODEL_IDENTITY));
|
||||||
|
|
||||||
return $response->noContent();
|
return $response->noContent();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ use Utopia\Database\Validator\UID;
|
||||||
use Utopia\Locale\Locale;
|
use Utopia\Locale\Locale;
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\Boolean;
|
use Utopia\Validator\Boolean;
|
||||||
|
use Utopia\Validator\Integer;
|
||||||
use Utopia\Validator\JSON;
|
use Utopia\Validator\JSON;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use MaxMind\Db\Reader;
|
use MaxMind\Db\Reader;
|
||||||
|
@ -54,21 +55,28 @@ App::post('/v1/messaging/providers/mailgun')
|
||||||
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
||||||
->param('providerId', '', new CustomId(), 'Provider 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('providerId', '', new CustomId(), 'Provider 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('name', '', new Text(128), 'Provider name.')
|
->param('name', '', new Text(128), 'Provider name.')
|
||||||
->param('from', '', new Email(), 'Sender email address.', true)
|
|
||||||
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
||||||
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
||||||
->param('isEuRegion', null, new Boolean(), 'Set as EU region.', true)
|
->param('isEuRegion', null, new Boolean(), 'Set as EU region.', true)
|
||||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||||
|
->param('fromName', '', new Text(128), 'Sender Name.', true)
|
||||||
|
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||||
|
->param('replyToName', '', new Text(128), 'Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.', true)
|
||||||
|
->param('replyToEmail', '', new Text(128), 'Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $providerId, string $name, string $from, string $apiKey, string $domain, ?bool $isEuRegion, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
->action(function (string $providerId, string $name, string $apiKey, string $domain, ?bool $isEuRegion, ?bool $enabled, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||||
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
||||||
|
|
||||||
$options = [];
|
$options = [
|
||||||
|
'fromName' => $fromName,
|
||||||
|
'fromEmail' => $fromEmail,
|
||||||
|
];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($replyToName) && !empty($replyToEmail)) {
|
||||||
$options ['from'] = $from;
|
$options['replyToName'] = $replyToName;
|
||||||
|
$options['replyToEmail'] = $replyToEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -137,19 +145,26 @@ App::post('/v1/messaging/providers/sendgrid')
|
||||||
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
||||||
->param('providerId', '', new CustomId(), 'Provider 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('providerId', '', new CustomId(), 'Provider 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('name', '', new Text(128), 'Provider name.')
|
->param('name', '', new Text(128), 'Provider name.')
|
||||||
->param('from', '', new Email(), 'Sender email address.', true)
|
|
||||||
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
||||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||||
|
->param('fromName', '', new Text(128), 'Sender Name.', true)
|
||||||
|
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||||
|
->param('replyToName', '', new Text(128), 'Name set in the reply to field for the mail. Default value is sender name.', true)
|
||||||
|
->param('replyToEmail', '', new Text(128), 'Email set in the reply to field for the mail. Default value is sender email.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $providerId, string $name, string $from, string $apiKey, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
->action(function (string $providerId, string $name, string $apiKey, ?bool $enabled, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||||
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
||||||
|
|
||||||
$options = [];
|
$options = [
|
||||||
|
'fromName' => $fromName,
|
||||||
|
'fromEmail' => $fromEmail,
|
||||||
|
];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($replyToName) && !empty($replyToEmail)) {
|
||||||
$options ['from'] = $from;
|
$options['replyToName'] = $replyToName;
|
||||||
|
$options['replyToEmail'] = $replyToEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -221,7 +236,7 @@ App::post('/v1/messaging/providers/msg91')
|
||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($from)) {
|
||||||
$options ['from'] = $from;
|
$options['from'] = $from;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -298,7 +313,7 @@ App::post('/v1/messaging/providers/telesign')
|
||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($from)) {
|
||||||
$options ['from'] = $from;
|
$options['from'] = $from;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -375,7 +390,7 @@ App::post('/v1/messaging/providers/textmagic')
|
||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($from)) {
|
||||||
$options ['from'] = $from;
|
$options['from'] = $from;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -452,7 +467,7 @@ App::post('/v1/messaging/providers/twilio')
|
||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($from)) {
|
||||||
$options ['from'] = $from;
|
$options['from'] = $from;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -529,7 +544,7 @@ App::post('/v1/messaging/providers/vonage')
|
||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if (!empty($from)) {
|
if (!empty($from)) {
|
||||||
$options ['from'] = $from;
|
$options['from'] = $from;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
@ -593,21 +608,21 @@ App::post('/v1/messaging/providers/fcm')
|
||||||
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
||||||
->param('providerId', '', new CustomId(), 'Provider 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('providerId', '', new CustomId(), 'Provider 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('name', '', new Text(128), 'Provider name.')
|
->param('name', '', new Text(128), 'Provider name.')
|
||||||
->param('serverKey', '', new Text(0), 'FCM server key.', true)
|
->param('serviceAccountJSON', null, new JSON(), 'FCM service account JSON.', true)
|
||||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $providerId, string $name, string $serverKey, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
->action(function (string $providerId, string $name, ?array $serviceAccountJSON, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||||
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
$providerId = $providerId == 'unique()' ? ID::unique() : $providerId;
|
||||||
|
|
||||||
$credentials = [];
|
$credentials = [];
|
||||||
|
|
||||||
if (!empty($serverKey)) {
|
if (!\is_null($serviceAccountJSON)) {
|
||||||
$credentials['serverKey'] = $serverKey;
|
$credentials['serviceAccountJSON'] = $serviceAccountJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($enabled === true && \array_key_exists('serverKey', $credentials)) {
|
if ($enabled === true && \array_key_exists('serviceAccountJSON', $credentials)) {
|
||||||
$enabled = true;
|
$enabled = true;
|
||||||
} else {
|
} else {
|
||||||
$enabled = false;
|
$enabled = false;
|
||||||
|
@ -888,15 +903,18 @@ App::patch('/v1/messaging/providers/mailgun/:providerId')
|
||||||
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
->label('sdk.response.model', Response::MODEL_PROVIDER)
|
||||||
->param('providerId', '', new UID(), 'Provider ID.')
|
->param('providerId', '', new UID(), 'Provider ID.')
|
||||||
->param('name', '', new Text(128), 'Provider name.', true)
|
->param('name', '', new Text(128), 'Provider name.', true)
|
||||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
|
||||||
->param('isEuRegion', null, new Boolean(), 'Set as EU region.', true)
|
|
||||||
->param('from', '', new Email(), 'Sender email address.', true)
|
|
||||||
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
->param('apiKey', '', new Text(0), 'Mailgun API Key.', true)
|
||||||
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
->param('domain', '', new Text(0), 'Mailgun Domain.', true)
|
||||||
|
->param('isEuRegion', null, new Boolean(), 'Set as EU region.', true)
|
||||||
|
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||||
|
->param('fromName', '', new Text(128), 'Sender Name.', true)
|
||||||
|
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||||
|
->param('replyToName', '', new Text(128), 'Name set in the reply to field for the mail. Default value is sender name.', true)
|
||||||
|
->param('replyToEmail', '', new Text(128), 'Email set in the reply to field for the mail. Default value is sender email.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $providerId, string $name, ?bool $enabled, ?bool $isEuRegion, string $from, string $apiKey, string $domain, Event $queueForEvents, Database $dbForProject, Response $response) {
|
->action(function (string $providerId, string $name, string $apiKey, string $domain, ?bool $isEuRegion, ?bool $enabled, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||||
$provider = $dbForProject->getDocument('providers', $providerId);
|
$provider = $dbForProject->getDocument('providers', $providerId);
|
||||||
|
|
||||||
if ($provider->isEmpty()) {
|
if ($provider->isEmpty()) {
|
||||||
|
@ -912,12 +930,26 @@ App::patch('/v1/messaging/providers/mailgun/:providerId')
|
||||||
$provider->setAttribute('name', $name);
|
$provider->setAttribute('name', $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($from)) {
|
$options = $provider->getAttribute('options');
|
||||||
$provider->setAttribute('options', [
|
|
||||||
'from' => $from,
|
if (!empty($fromName)) {
|
||||||
]);
|
$options['fromName'] = $fromName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($fromEmail)) {
|
||||||
|
$options['fromEmail'] = $fromEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($replyToName)) {
|
||||||
|
$options['replyToName'] = $replyToName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($replyToEmail)) {
|
||||||
|
$options['replyToEmail'] = $replyToEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
$provider->setAttribute('options', $options);
|
||||||
|
|
||||||
$credentials = $provider->getAttribute('credentials');
|
$credentials = $provider->getAttribute('credentials');
|
||||||
|
|
||||||
if ($isEuRegion === true || $isEuRegion === false) {
|
if ($isEuRegion === true || $isEuRegion === false) {
|
||||||
|
@ -976,11 +1008,14 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId')
|
||||||
->param('name', '', new Text(128), 'Provider name.', true)
|
->param('name', '', new Text(128), 'Provider name.', true)
|
||||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||||
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
->param('apiKey', '', new Text(0), 'Sendgrid API key.', true)
|
||||||
->param('from', '', new Email(), 'Sender email address.', true)
|
->param('fromName', '', new Text(128), 'Sender Name.', true)
|
||||||
|
->param('fromEmail', '', new Email(), 'Sender email address.', true)
|
||||||
|
->param('replyToName', '', new Text(128), 'Name set in the Reply To field for the mail. Default value is Sender Name.', true)
|
||||||
|
->param('replyToEmail', '', new Text(128), 'Email set in the Reply To field for the mail. Default value is Sender Email.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $providerId, string $name, ?bool $enabled, string $apiKey, string $from, Event $queueForEvents, Database $dbForProject, Response $response) {
|
->action(function (string $providerId, string $name, ?bool $enabled, string $apiKey, string $fromName, string $fromEmail, string $replyToName, string $replyToEmail, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||||
$provider = $dbForProject->getDocument('providers', $providerId);
|
$provider = $dbForProject->getDocument('providers', $providerId);
|
||||||
|
|
||||||
if ($provider->isEmpty()) {
|
if ($provider->isEmpty()) {
|
||||||
|
@ -996,12 +1031,26 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId')
|
||||||
$provider->setAttribute('name', $name);
|
$provider->setAttribute('name', $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($from)) {
|
$options = $provider->getAttribute('options');
|
||||||
$provider->setAttribute('options', [
|
|
||||||
'from' => $from,
|
if (!empty($fromName)) {
|
||||||
]);
|
$options['fromName'] = $fromName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($fromEmail)) {
|
||||||
|
$options['fromEmail'] = $fromEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($replyToName)) {
|
||||||
|
$options['replyToName'] = $replyToName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($replyToEmail)) {
|
||||||
|
$options['replyToEmail'] = $replyToEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
$provider->setAttribute('options', $options);
|
||||||
|
|
||||||
if (!empty($apiKey)) {
|
if (!empty($apiKey)) {
|
||||||
$provider->setAttribute('credentials', [
|
$provider->setAttribute('credentials', [
|
||||||
'apiKey' => $apiKey,
|
'apiKey' => $apiKey,
|
||||||
|
@ -1451,11 +1500,11 @@ App::patch('/v1/messaging/providers/fcm/:providerId')
|
||||||
->param('providerId', '', new UID(), 'Provider ID.')
|
->param('providerId', '', new UID(), 'Provider ID.')
|
||||||
->param('name', '', new Text(128), 'Provider name.', true)
|
->param('name', '', new Text(128), 'Provider name.', true)
|
||||||
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
->param('enabled', null, new Boolean(), 'Set as enabled.', true)
|
||||||
->param('serverKey', '', new Text(0), 'FCM Server Key.', true)
|
->param('serviceAccountJSON', null, new JSON(), 'FCM service account JSON.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $providerId, string $name, ?bool $enabled, string $serverKey, Event $queueForEvents, Database $dbForProject, Response $response) {
|
->action(function (string $providerId, string $name, ?bool $enabled, ?array $serviceAccountJSON, Event $queueForEvents, Database $dbForProject, Response $response) {
|
||||||
$provider = $dbForProject->getDocument('providers', $providerId);
|
$provider = $dbForProject->getDocument('providers', $providerId);
|
||||||
|
|
||||||
if ($provider->isEmpty()) {
|
if ($provider->isEmpty()) {
|
||||||
|
@ -1471,12 +1520,12 @@ App::patch('/v1/messaging/providers/fcm/:providerId')
|
||||||
$provider->setAttribute('name', $name);
|
$provider->setAttribute('name', $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($serverKey)) {
|
if (!\is_null($serviceAccountJSON)) {
|
||||||
$provider->setAttribute('credentials', ['serverKey' => $serverKey]);
|
$provider->setAttribute('credentials', ['serviceAccountJSON' => $serviceAccountJSON]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($enabled === true || $enabled === false) {
|
if ($enabled === true || $enabled === false) {
|
||||||
if ($enabled === true && \array_key_exists('serverKey', $provider->getAttribute('credentials'))) {
|
if ($enabled === true && \array_key_exists('serviceAccountJSON', $provider->getAttribute('credentials'))) {
|
||||||
$enabled = true;
|
$enabled = true;
|
||||||
} else {
|
} else {
|
||||||
$enabled = false;
|
$enabled = false;
|
||||||
|
@ -2227,9 +2276,11 @@ App::post('/v1/messaging/messages/email')
|
||||||
->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('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('subject', '', new Text(998), 'Email Subject.')
|
->param('subject', '', new Text(998), 'Email Subject.')
|
||||||
->param('content', '', new Text(64230), 'Email Content.')
|
->param('content', '', new Text(64230), 'Email Content.')
|
||||||
->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs.', true)
|
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||||
->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of User IDs.', true)
|
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||||
->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Targets IDs.', true)
|
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||||
|
->param('cc', [], new ArrayList(new UID()), 'Array of target IDs to be added as CC.', true)
|
||||||
|
->param('bcc', [], new ArrayList(new UID()), 'Array of target IDs to be added as BCC.', true)
|
||||||
->param('description', '', new Text(256), 'Description for message.', true)
|
->param('description', '', new Text(256), 'Description for message.', true)
|
||||||
->param('status', 'processing', new WhiteList(['draft', 'canceled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
->param('status', 'processing', new WhiteList(['draft', 'canceled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
||||||
->param('html', false, new Boolean(), 'Is content of type HTML', true)
|
->param('html', false, new Boolean(), 'Is content of type HTML', true)
|
||||||
|
@ -2239,22 +2290,32 @@ App::post('/v1/messaging/messages/email')
|
||||||
->inject('project')
|
->inject('project')
|
||||||
->inject('queueForMessaging')
|
->inject('queueForMessaging')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, string $description, string $status, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, string $description, string $status, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||||
$messageId = $messageId == 'unique()' ? ID::unique() : $messageId;
|
$messageId = $messageId == 'unique()'
|
||||||
|
? ID::unique()
|
||||||
|
: $messageId;
|
||||||
|
|
||||||
if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) {
|
if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) {
|
||||||
throw new Exception(Exception::MESSAGE_MISSING_TARGET);
|
throw new Exception(Exception::MESSAGE_MISSING_TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($targets as $target) {
|
$mergedTargets = \array_merge($targets, $cc, $bcc);
|
||||||
$targetDocument = $dbForProject->getDocument('targets', $target);
|
|
||||||
|
|
||||||
if ($targetDocument->isEmpty()) {
|
if (!empty($mergedTargets)) {
|
||||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
$foundTargets = $dbForProject->find('targets', [
|
||||||
|
Query::equal('$id', $mergedTargets),
|
||||||
|
Query::equal('providerType', [MESSAGE_TYPE_EMAIL]),
|
||||||
|
Query::limit(\count($mergedTargets)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (\count($foundTargets) !== \count($mergedTargets)) {
|
||||||
|
throw new Exception(Exception::MESSAGE_TARGET_NOT_EMAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($targetDocument->getAttribute('providerType') !== MESSAGE_TYPE_EMAIL) {
|
foreach ($foundTargets as $target) {
|
||||||
throw new Exception(Exception::MESSAGE_TARGET_NOT_EMAIL . ' ' . $targetDocument->getId());
|
if ($target->isEmpty()) {
|
||||||
|
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2269,6 +2330,8 @@ App::post('/v1/messaging/messages/email')
|
||||||
'subject' => $subject,
|
'subject' => $subject,
|
||||||
'content' => $content,
|
'content' => $content,
|
||||||
'html' => $html,
|
'html' => $html,
|
||||||
|
'cc' => $cc,
|
||||||
|
'bcc' => $bcc,
|
||||||
],
|
],
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
]));
|
]));
|
||||||
|
@ -2304,9 +2367,9 @@ App::post('/v1/messaging/messages/sms')
|
||||||
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
->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('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('content', '', new Text(64230), 'SMS Content.')
|
->param('content', '', new Text(64230), 'SMS Content.')
|
||||||
->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs.', true)
|
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||||
->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of User IDs.', true)
|
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||||
->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Targets IDs.', true)
|
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
->param('description', '', new Text(256), 'Description for Message.', true)
|
||||||
->param('status', 'processing', new WhiteList(['draft', 'canceled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
->param('status', 'processing', new WhiteList(['draft', 'canceled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
||||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||||
|
@ -2316,22 +2379,28 @@ App::post('/v1/messaging/messages/sms')
|
||||||
->inject('queueForMessaging')
|
->inject('queueForMessaging')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $messageId, string $content, array $topics, array $users, array $targets, string $description, string $status, ?string $scheduledAt, Event $queueForEvents, 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 $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||||
$messageId = $messageId == 'unique()' ? ID::unique() : $messageId;
|
$messageId = $messageId == 'unique()'
|
||||||
|
? ID::unique()
|
||||||
|
: $messageId;
|
||||||
|
|
||||||
if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) {
|
if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) {
|
||||||
throw new Exception(Exception::MESSAGE_MISSING_TARGET);
|
throw new Exception(Exception::MESSAGE_MISSING_TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($targets as $target) {
|
$foundTargets = $dbForProject->find('targets', [
|
||||||
$targetDocument = $dbForProject->getDocument('targets', $target);
|
Query::equal('$id', $targets),
|
||||||
|
Query::equal('providerType', [MESSAGE_TYPE_SMS]),
|
||||||
|
Query::limit(\count($targets)),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($targetDocument->isEmpty()) {
|
if (\count($foundTargets) !== \count($targets)) {
|
||||||
|
throw new Exception(Exception::MESSAGE_TARGET_NOT_SMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($foundTargets as $target) {
|
||||||
|
if ($target->isEmpty()) {
|
||||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($targetDocument->getAttribute('providerType') !== MESSAGE_TYPE_SMS) {
|
|
||||||
throw new Exception(Exception::MESSAGE_TARGET_NOT_SMS . ' ' . $targetDocument->getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$message = $dbForProject->createDocument('messages', new Document([
|
$message = $dbForProject->createDocument('messages', new Document([
|
||||||
|
@ -2379,9 +2448,9 @@ App::post('/v1/messaging/messages/push')
|
||||||
->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('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('title', '', new Text(256), 'Title for push notification.')
|
->param('title', '', new Text(256), 'Title for push notification.')
|
||||||
->param('body', '', new Text(64230), 'Body for push notification.')
|
->param('body', '', new Text(64230), 'Body for push notification.')
|
||||||
->param('topics', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs.', true)
|
->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||||
->param('users', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of User IDs.', true)
|
->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true)
|
||||||
->param('targets', [], new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Targets IDs.', true)
|
->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
->param('description', '', new Text(256), 'Description for Message.', true)
|
||||||
->param('data', null, new JSON(), 'Additional Data for push notification.', true)
|
->param('data', null, new JSON(), 'Additional Data for push notification.', true)
|
||||||
->param('action', '', new Text(256), 'Action for push notification.', true)
|
->param('action', '', new Text(256), 'Action for push notification.', true)
|
||||||
|
@ -2398,22 +2467,28 @@ App::post('/v1/messaging/messages/push')
|
||||||
->inject('queueForMessaging')
|
->inject('queueForMessaging')
|
||||||
->inject('response')
|
->inject('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 $scheduledAt, Event $queueForEvents, 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 $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||||
$messageId = $messageId == 'unique()' ? ID::unique() : $messageId;
|
$messageId = $messageId == 'unique()'
|
||||||
|
? ID::unique()
|
||||||
|
: $messageId;
|
||||||
|
|
||||||
if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) {
|
if (\count($topics) === 0 && \count($users) === 0 && \count($targets) === 0) {
|
||||||
throw new Exception(Exception::MESSAGE_MISSING_TARGET);
|
throw new Exception(Exception::MESSAGE_MISSING_TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($targets as $target) {
|
$foundTargets = $dbForProject->find('targets', [
|
||||||
$targetDocument = $dbForProject->getDocument('targets', $target);
|
Query::equal('$id', $targets),
|
||||||
|
Query::equal('providerType', [MESSAGE_TYPE_PUSH]),
|
||||||
|
Query::limit(\count($targets)),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($targetDocument->isEmpty()) {
|
if (\count($foundTargets) !== \count($targets)) {
|
||||||
|
throw new Exception(Exception::MESSAGE_TARGET_NOT_PUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($foundTargets as $target) {
|
||||||
|
if ($target->isEmpty()) {
|
||||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($targetDocument->getAttribute('providerType') !== MESSAGE_TYPE_PUSH) {
|
|
||||||
throw new Exception(Exception::MESSAGE_TARGET_NOT_PUSH . ' ' . $targetDocument->getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$pushData = [];
|
$pushData = [];
|
||||||
|
@ -2619,21 +2694,23 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
||||||
->param('messageId', '', new UID(), 'Message ID.')
|
->param('messageId', '', new UID(), 'Message ID.')
|
||||||
->param('topics', null, new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Topic IDs.', true)
|
->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||||
->param('users', null, new ArrayList(new Text(Database::LENGTH_KEY)), 'List of User IDs.', true)
|
->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true)
|
||||||
->param('targets', null, new ArrayList(new Text(Database::LENGTH_KEY)), 'List of Targets IDs.', true)
|
->param('targets', null, new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||||
->param('subject', '', new Text(998), 'Email Subject.', true)
|
->param('subject', null, new Text(998), 'Email Subject.', true)
|
||||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
->param('description', null, new Text(256), 'Description for Message.', true)
|
||||||
->param('content', '', new Text(64230), 'Email Content.', true)
|
->param('content', null, new Text(64230), 'Email Content.', true)
|
||||||
->param('status', '', new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
->param('status', null, new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
||||||
->param('html', false, new Boolean(), 'Is content of type HTML', true)
|
->param('html', null, new Boolean(), 'Is content of type HTML', true)
|
||||||
|
->param('cc', null, new ArrayList(new UID()), 'Array of target IDs to be added as CC.', true)
|
||||||
|
->param('bcc', null, new ArrayList(new UID()), 'Array of target IDs to be added as BCC.', true)
|
||||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('project')
|
->inject('project')
|
||||||
->inject('queueForMessaging')
|
->inject('queueForMessaging')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, string $subject, string $description, string $content, string $status, bool $html, ?string $scheduledAt, Event $queueForEvents, 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, ?array $cc, ?array $bcc, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||||
$message = $dbForProject->getDocument('messages', $messageId);
|
$message = $dbForProject->getDocument('messages', $messageId);
|
||||||
|
|
||||||
if ($message->isEmpty()) {
|
if ($message->isEmpty()) {
|
||||||
|
@ -2644,7 +2721,7 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||||
throw new Exception(Exception::MESSAGE_ALREADY_SENT);
|
throw new Exception(Exception::MESSAGE_ALREADY_SENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_null($message->getAttribute('scheduledAt')) && $message->getAttribute('scheduledAt') < new \DateTime()) {
|
if (!\is_null($message->getAttribute('scheduledAt')) && $message->getAttribute('scheduledAt') < new \DateTime()) {
|
||||||
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
|
throw new Exception(Exception::MESSAGE_ALREADY_SCHEDULED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2656,43 +2733,57 @@ App::patch('/v1/messaging/messages/email/:messageId')
|
||||||
$message->setAttribute('users', $users);
|
$message->setAttribute('users', $users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\is_null($targets)) {
|
if (!\is_null($targets) || !\is_null($cc) || !\is_null($bcc)) {
|
||||||
foreach ($targets as $target) {
|
$mergedTargets = \array_merge(...\array_filter([$targets, $cc, $bcc]));
|
||||||
$targetDocument = $dbForProject->getDocument('targets', $target);
|
|
||||||
|
|
||||||
if ($targetDocument->isEmpty()) {
|
$foundTargets = $dbForProject->find('targets', [
|
||||||
|
Query::equal('$id', $mergedTargets),
|
||||||
|
Query::equal('providerType', [MESSAGE_TYPE_EMAIL]),
|
||||||
|
Query::limit(\count($mergedTargets)),
|
||||||
|
]);
|
||||||
|
if (\count($foundTargets) !== \count($mergedTargets)) {
|
||||||
|
throw new Exception(Exception::MESSAGE_TARGET_NOT_EMAIL);
|
||||||
|
}
|
||||||
|
foreach ($foundTargets as $target) {
|
||||||
|
if ($target->isEmpty()) {
|
||||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($targetDocument->getAttribute('providerType') !== MESSAGE_TYPE_EMAIL) {
|
|
||||||
throw new Exception(Exception::MESSAGE_TARGET_NOT_EMAIL . ' ' . $targetDocument->getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$message->setAttribute('targets', $targets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $message->getAttribute('data');
|
$data = $message->getAttribute('data');
|
||||||
|
|
||||||
if (!empty($subject)) {
|
if (!\is_null($targets)) {
|
||||||
|
$message->setAttribute('targets', $targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_null($subject)) {
|
||||||
$data['subject'] = $subject;
|
$data['subject'] = $subject;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($content)) {
|
if (!\is_null($content)) {
|
||||||
$data['content'] = $content;
|
$data['content'] = $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($html)) {
|
if (!\is_null($html)) {
|
||||||
$data['html'] = $html;
|
$data['html'] = $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!\is_null($cc)) {
|
||||||
|
$data['cc'] = $cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_null($bcc)) {
|
||||||
|
$data['bcc'] = $bcc;
|
||||||
|
}
|
||||||
|
|
||||||
$message->setAttribute('data', $data);
|
$message->setAttribute('data', $data);
|
||||||
|
|
||||||
if (!empty($description)) {
|
if (!\is_null($description)) {
|
||||||
$message->setAttribute('description', $description);
|
$message->setAttribute('description', $description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($status)) {
|
if (!\is_null($status)) {
|
||||||
$message->setAttribute('status', $status);
|
$message->setAttribute('status', $status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2731,19 +2822,19 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
||||||
->param('messageId', '', new UID(), 'Message ID.')
|
->param('messageId', '', new UID(), 'Message ID.')
|
||||||
->param('topics', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true)
|
->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||||
->param('users', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true)
|
->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true)
|
||||||
->param('targets', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true)
|
->param('targets', null, new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
->param('description', null, new Text(256), 'Description for Message.', true)
|
||||||
->param('content', '', new Text(64230), 'Email Content.', true)
|
->param('content', null, new Text(64230), 'Email Content.', true)
|
||||||
->param('status', '', new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
->param('status', null, new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
||||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('project')
|
->inject('project')
|
||||||
->inject('queueForMessaging')
|
->inject('queueForMessaging')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, string $description, string $content, string $status, ?string $scheduledAt, Event $queueForEvents, 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 $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||||
$message = $dbForProject->getDocument('messages', $messageId);
|
$message = $dbForProject->getDocument('messages', $messageId);
|
||||||
|
|
||||||
if ($message->isEmpty()) {
|
if ($message->isEmpty()) {
|
||||||
|
@ -2767,16 +2858,20 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\is_null($targets)) {
|
if (!\is_null($targets)) {
|
||||||
foreach ($targets as $target) {
|
$foundTargets = $dbForProject->find('targets', [
|
||||||
$targetDocument = $dbForProject->getDocument('targets', $target);
|
Query::equal('$id', $targets),
|
||||||
|
Query::equal('providerType', [MESSAGE_TYPE_SMS]),
|
||||||
|
Query::limit(\count($targets)),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($targetDocument->isEmpty()) {
|
if (\count($foundTargets) !== \count($targets)) {
|
||||||
|
throw new Exception(Exception::MESSAGE_TARGET_NOT_SMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($foundTargets as $target) {
|
||||||
|
if ($target->isEmpty()) {
|
||||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($targetDocument->getAttribute('providerType') !== MESSAGE_TYPE_SMS) {
|
|
||||||
throw new Exception(Exception::MESSAGE_TARGET_NOT_SMS . ' ' . $targetDocument->getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$message->setAttribute('targets', $targets);
|
$message->setAttribute('targets', $targets);
|
||||||
|
@ -2784,17 +2879,17 @@ App::patch('/v1/messaging/messages/sms/:messageId')
|
||||||
|
|
||||||
$data = $message->getAttribute('data');
|
$data = $message->getAttribute('data');
|
||||||
|
|
||||||
if (!empty($content)) {
|
if (!\is_null($content)) {
|
||||||
$data['content'] = $content;
|
$data['content'] = $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
$message->setAttribute('data', $data);
|
$message->setAttribute('data', $data);
|
||||||
|
|
||||||
if (!empty($status)) {
|
if (!\is_null($status)) {
|
||||||
$message->setAttribute('status', $status);
|
$message->setAttribute('status', $status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($description)) {
|
if (!\is_null($description)) {
|
||||||
$message->setAttribute('description', $description);
|
$message->setAttribute('description', $description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2833,27 +2928,27 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
->label('sdk.response.model', Response::MODEL_MESSAGE)
|
||||||
->param('messageId', '', new UID(), 'Message ID.')
|
->param('messageId', '', new UID(), 'Message ID.')
|
||||||
->param('topics', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Topic IDs.', true)
|
->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true)
|
||||||
->param('users', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of User IDs.', true)
|
->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true)
|
||||||
->param('targets', null, new ArrayList(new Text(Database::LENGTH_KEY), 1), 'List of Targets IDs.', true)
|
->param('targets', null, new ArrayList(new UID()), 'List of Targets IDs.', true)
|
||||||
->param('description', '', new Text(256), 'Description for Message.', true)
|
->param('description', null, new Text(256), 'Description for Message.', true)
|
||||||
->param('title', '', new Text(256), 'Title for push notification.', true)
|
->param('title', null, new Text(256), 'Title for push notification.', true)
|
||||||
->param('body', '', new Text(64230), 'Body for push notification.', true)
|
->param('body', null, new Text(64230), 'Body for push notification.', true)
|
||||||
->param('data', null, new JSON(), 'Additional Data for push notification.', true)
|
->param('data', null, new JSON(), 'Additional Data for push notification.', true)
|
||||||
->param('action', '', new Text(256), 'Action for push notification.', true)
|
->param('action', null, new Text(256), 'Action for push notification.', true)
|
||||||
->param('icon', '', new Text(256), 'Icon for push notification. Available only for Android and Web Platform.', true)
|
->param('icon', null, new Text(256), 'Icon for push notification. Available only for Android and Web platforms.', true)
|
||||||
->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and IOS Platform.', true)
|
->param('sound', null, new Text(256), 'Sound for push notification. Available only for Android and iOS platforms.', true)
|
||||||
->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true)
|
->param('color', null, new Text(256), 'Color for push notification. Available only for Android platforms.', true)
|
||||||
->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true)
|
->param('tag', null, new Text(256), 'Tag for push notification. Available only for Android platforms.', true)
|
||||||
->param('badge', '', new Text(256), 'Badge for push notification. Available only for IOS Platform.', true)
|
->param('badge', null, new Integer(), 'Badge for push notification. Available only for iOS platforms.', true)
|
||||||
->param('status', '', new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft or cancelled or processing.', true)
|
->param('status', null, new WhiteList(['draft', 'cancelled', 'processing']), 'Message Status. Value must be either draft, cancelled, or processing.', true)
|
||||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled delivery time for message in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||||
->inject('queueForEvents')
|
->inject('queueForEvents')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->inject('project')
|
->inject('project')
|
||||||
->inject('queueForMessaging')
|
->inject('queueForMessaging')
|
||||||
->inject('response')
|
->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 $scheduledAt, Event $queueForEvents, 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, ?int $badge, ?string $status, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Document $project, Messaging $queueForMessaging, Response $response) {
|
||||||
$message = $dbForProject->getDocument('messages', $messageId);
|
$message = $dbForProject->getDocument('messages', $messageId);
|
||||||
|
|
||||||
if ($message->isEmpty()) {
|
if ($message->isEmpty()) {
|
||||||
|
@ -2877,16 +2972,20 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\is_null($targets)) {
|
if (!\is_null($targets)) {
|
||||||
foreach ($targets as $target) {
|
$foundTargets = $dbForProject->find('targets', [
|
||||||
$targetDocument = $dbForProject->getDocument('targets', $target);
|
Query::equal('$id', $targets),
|
||||||
|
Query::equal('providerType', [MESSAGE_TYPE_PUSH]),
|
||||||
|
Query::limit(\count($targets)),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($targetDocument->isEmpty()) {
|
if (\count($foundTargets) !== \count($targets)) {
|
||||||
|
throw new Exception(Exception::MESSAGE_TARGET_NOT_PUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($foundTargets as $target) {
|
||||||
|
if ($target->isEmpty()) {
|
||||||
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
throw new Exception(Exception::USER_TARGET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($targetDocument->getAttribute('providerType') !== MESSAGE_TYPE_PUSH) {
|
|
||||||
throw new Exception(Exception::MESSAGE_TARGET_NOT_PUSH . ' ' . $targetDocument->getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$message->setAttribute('targets', $targets);
|
$message->setAttribute('targets', $targets);
|
||||||
|
@ -2894,53 +2993,53 @@ App::patch('/v1/messaging/messages/push/:messageId')
|
||||||
|
|
||||||
$pushData = $message->getAttribute('data');
|
$pushData = $message->getAttribute('data');
|
||||||
|
|
||||||
if ($title) {
|
if (!\is_null($title)) {
|
||||||
$pushData['title'] = $title;
|
$pushData['title'] = $title;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($body) {
|
if (!\is_null($body)) {
|
||||||
$pushData['body'] = $body;
|
$pushData['body'] = $body;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_null($data)) {
|
if (!\is_null($data)) {
|
||||||
$pushData['data'] = $data;
|
$pushData['data'] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($action) {
|
if (!\is_null($action)) {
|
||||||
$pushData['action'] = $action;
|
$pushData['action'] = $action;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($icon) {
|
if (!\is_null($icon)) {
|
||||||
$pushData['icon'] = $icon;
|
$pushData['icon'] = $icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($sound) {
|
if (!\is_null($sound)) {
|
||||||
$pushData['sound'] = $sound;
|
$pushData['sound'] = $sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($color) {
|
if (!\is_null($color)) {
|
||||||
$pushData['color'] = $color;
|
$pushData['color'] = $color;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tag) {
|
if (!\is_null($tag)) {
|
||||||
$pushData['tag'] = $tag;
|
$pushData['tag'] = $tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($badge) {
|
if (!\is_null($badge)) {
|
||||||
$pushData['badge'] = $badge;
|
$pushData['badge'] = $badge;
|
||||||
}
|
}
|
||||||
|
|
||||||
$message->setAttribute('data', $pushData);
|
$message->setAttribute('data', $pushData);
|
||||||
|
|
||||||
if (!empty($status)) {
|
if (!\is_null($status)) {
|
||||||
$message->setAttribute('status', $status);
|
$message->setAttribute('status', $status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($description)) {
|
if (!\is_null($description)) {
|
||||||
$message->setAttribute('description', $description);
|
$message->setAttribute('description', $description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_null($scheduledAt)) {
|
if (!\is_null($scheduledAt)) {
|
||||||
$message->setAttribute('scheduledAt', $scheduledAt);
|
$message->setAttribute('scheduledAt', $scheduledAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1598,7 +1598,7 @@ App::delete('/v1/users/:userId/targets/:targetId')
|
||||||
});
|
});
|
||||||
|
|
||||||
App::delete('/v1/users/identities/:identityId')
|
App::delete('/v1/users/identities/:identityId')
|
||||||
->desc('Delete Identity')
|
->desc('Delete identity')
|
||||||
->groups(['api', 'users'])
|
->groups(['api', 'users'])
|
||||||
->label('event', 'users.[userId].identities.[identityId].delete')
|
->label('event', 'users.[userId].identities.[identityId].delete')
|
||||||
->label('scope', 'users.write')
|
->label('scope', 'users.write')
|
||||||
|
@ -1614,7 +1614,8 @@ App::delete('/v1/users/identities/:identityId')
|
||||||
->param('identityId', '', new UID(), 'Identity ID.')
|
->param('identityId', '', new UID(), 'Identity ID.')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
->inject('dbForProject')
|
->inject('dbForProject')
|
||||||
->action(function (string $identityId, Response $response, Database $dbForProject) {
|
->inject('queueForEvents')
|
||||||
|
->action(function (string $identityId, Response $response, Database $dbForProject, Event $queueForEvents) {
|
||||||
|
|
||||||
$identity = $dbForProject->getDocument('identities', $identityId);
|
$identity = $dbForProject->getDocument('identities', $identityId);
|
||||||
|
|
||||||
|
@ -1624,6 +1625,11 @@ App::delete('/v1/users/identities/:identityId')
|
||||||
|
|
||||||
$dbForProject->deleteDocument('identities', $identityId);
|
$dbForProject->deleteDocument('identities', $identityId);
|
||||||
|
|
||||||
|
$queueForEvents
|
||||||
|
->setParam('userId', $identity->getAttribute('userId'))
|
||||||
|
->setParam('identityId', $identity->getId())
|
||||||
|
->setPayload($response->output($identity, Response::MODEL_IDENTITY));
|
||||||
|
|
||||||
return $response->noContent();
|
return $response->noContent();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ $worker
|
||||||
|
|
||||||
$worker->workerStart()
|
$worker->workerStart()
|
||||||
->action(function () use ($workerName) {
|
->action(function () use ($workerName) {
|
||||||
Console::info("Worker $workerName started");
|
Console::info("Worker $workerName started");
|
||||||
});
|
});
|
||||||
|
|
||||||
$worker->start();
|
$worker->start();
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"utopia-php/image": "0.5.*",
|
"utopia-php/image": "0.5.*",
|
||||||
"utopia-php/locale": "0.4.*",
|
"utopia-php/locale": "0.4.*",
|
||||||
"utopia-php/logger": "0.3.*",
|
"utopia-php/logger": "0.3.*",
|
||||||
"utopia-php/messaging": "0.2.*",
|
"utopia-php/messaging": "0.8.*",
|
||||||
"utopia-php/migration": "0.3.*",
|
"utopia-php/migration": "0.3.*",
|
||||||
"utopia-php/orchestration": "0.9.*",
|
"utopia-php/orchestration": "0.9.*",
|
||||||
"utopia-php/platform": "0.5.*",
|
"utopia-php/platform": "0.5.*",
|
||||||
|
|
20
composer.lock
generated
20
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "92b527993518d6b893e3d226064edac0",
|
"content-hash": "359b1e3bd27ac7362c6f8d145e64ae36",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/jwt",
|
"name": "adhocore/jwt",
|
||||||
|
@ -2272,26 +2272,28 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/messaging",
|
"name": "utopia-php/messaging",
|
||||||
"version": "0.2.0",
|
"version": "0.8.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/utopia-php/messaging.git",
|
"url": "https://github.com/utopia-php/messaging.git",
|
||||||
"reference": "2d0f474a106bb1da285f85e105c29b46085d3a43"
|
"reference": "64eca3faf02a79831f219d4f3ae05cd278a88b4b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/2d0f474a106bb1da285f85e105c29b46085d3a43",
|
"url": "https://api.github.com/repos/utopia-php/messaging/zipball/64eca3faf02a79831f219d4f3ae05cd278a88b4b",
|
||||||
"reference": "2d0f474a106bb1da285f85e105c29b46085d3a43",
|
"reference": "64eca3faf02a79831f219d4f3ae05cd278a88b4b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
|
"ext-openssl": "*",
|
||||||
"php": ">=8.0.0"
|
"php": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"laravel/pint": "^1.2",
|
"laravel/pint": "1.13.*",
|
||||||
"phpmailer/phpmailer": "6.8.*",
|
"phpmailer/phpmailer": "6.8.*",
|
||||||
"phpunit/phpunit": "9.6.*"
|
"phpstan/phpstan": "1.10.*",
|
||||||
|
"phpunit/phpunit": "9.6.10"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -2314,9 +2316,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/utopia-php/messaging/issues",
|
"issues": "https://github.com/utopia-php/messaging/issues",
|
||||||
"source": "https://github.com/utopia-php/messaging/tree/0.2.0"
|
"source": "https://github.com/utopia-php/messaging/tree/0.8.0"
|
||||||
},
|
},
|
||||||
"time": "2023-09-14T20:48:42+00:00"
|
"time": "2023-12-15T06:44:08+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "utopia-php/migration",
|
"name": "utopia-php/migration",
|
||||||
|
|
|
@ -8,6 +8,7 @@ use Appwrite\Docker\Env;
|
||||||
use Appwrite\Utopia\View;
|
use Appwrite\Utopia\View;
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Platform\Action;
|
use Utopia\Platform\Action;
|
||||||
|
|
||||||
|
@ -24,15 +25,16 @@ class Install extends Action
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->desc('Install Appwrite')
|
->desc('Install Appwrite')
|
||||||
->param('httpPort', '', new Text(4), 'Server HTTP port', true)
|
->param('http-port', '', new Text(4), 'Server HTTP port', true)
|
||||||
->param('httpsPort', '', new Text(4), 'Server HTTPS port', true)
|
->param('https-port', '', new Text(4), 'Server HTTPS port', true)
|
||||||
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
|
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
|
||||||
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
|
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
|
||||||
->param('interactive', 'Y', new Text(1), 'Run an interactive session', true)
|
->param('interactive', 'Y', new Text(1), 'Run an interactive session', true)
|
||||||
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive));
|
->param('no-start', false, new Boolean(true), 'Run an interactive session', true)
|
||||||
|
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive, $noStart) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive): void
|
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void
|
||||||
{
|
{
|
||||||
$config = Config::getParam('variables');
|
$config = Config::getParam('variables');
|
||||||
$defaultHTTPPort = '80';
|
$defaultHTTPPort = '80';
|
||||||
|
@ -220,9 +222,11 @@ class Install extends Action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::log("Running \"docker compose up -d --remove-orphans --renew-anon-volumes\"");
|
$exit = 0;
|
||||||
|
if (!$noStart) {
|
||||||
$exit = Console::execute("$env docker compose --project-directory $this->path up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr);
|
Console::log("Running \"docker compose up -d --remove-orphans --renew-anon-volumes\"");
|
||||||
|
$exit = Console::execute("$env docker compose --project-directory $this->path up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr);
|
||||||
|
}
|
||||||
|
|
||||||
if ($exit !== 0) {
|
if ($exit !== 0) {
|
||||||
$message = 'Failed to install Appwrite dockers';
|
$message = 'Failed to install Appwrite dockers';
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Appwrite\Platform\Tasks;
|
namespace Appwrite\Platform\Tasks;
|
||||||
|
|
||||||
use Utopia\CLI\Console;
|
use Utopia\CLI\Console;
|
||||||
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
|
|
||||||
class Upgrade extends Install
|
class Upgrade extends Install
|
||||||
|
@ -16,15 +17,16 @@ class Upgrade extends Install
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->desc('Upgrade Appwrite')
|
->desc('Upgrade Appwrite')
|
||||||
->param('httpPort', '', new Text(4), 'Server HTTP port', true)
|
->param('http-port', '', new Text(4), 'Server HTTP port', true)
|
||||||
->param('httpsPort', '', new Text(4), 'Server HTTPS port', true)
|
->param('https-port', '', new Text(4), 'Server HTTPS port', true)
|
||||||
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
|
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
|
||||||
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
|
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
|
||||||
->param('interactive', 'Y', new Text(1), 'Run an interactive session', true)
|
->param('interactive', 'Y', new Text(1), 'Run an interactive session', true)
|
||||||
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive));
|
->param('no-start', false, new Boolean(true), 'Run an interactive session', true)
|
||||||
|
->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive, $noStart) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive): void
|
public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void
|
||||||
{
|
{
|
||||||
// Check for previous installation
|
// Check for previous installation
|
||||||
$data = @file_get_contents($this->path . '/docker-compose.yml');
|
$data = @file_get_contents($this->path . '/docker-compose.yml');
|
||||||
|
@ -37,6 +39,6 @@ class Upgrade extends Install
|
||||||
Console::log(' └── docker-compose.yml');
|
Console::log(' └── docker-compose.yml');
|
||||||
Console::exit(1);
|
Console::exit(1);
|
||||||
}
|
}
|
||||||
parent::action($httpPort, $httpsPort, $organization, $image, $interactive);
|
parent::action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,22 +13,23 @@ use Utopia\Database\Database;
|
||||||
use Utopia\Database\DateTime;
|
use Utopia\Database\DateTime;
|
||||||
use Utopia\Database\Document;
|
use Utopia\Database\Document;
|
||||||
use Utopia\Database\Query;
|
use Utopia\Database\Query;
|
||||||
use Utopia\Messaging\Adapters\SMS as SMSAdapter;
|
use Utopia\Messaging\Adapter\Email as EmailAdapter;
|
||||||
use Utopia\Messaging\Adapters\SMS\Mock;
|
use Utopia\Messaging\Adapter\Email\Mailgun;
|
||||||
use Utopia\Messaging\Adapters\SMS\Msg91;
|
use Utopia\Messaging\Adapter\Email\Sendgrid;
|
||||||
use Utopia\Messaging\Adapters\SMS\Telesign;
|
use Utopia\Messaging\Adapter\Push as PushAdapter;
|
||||||
use Utopia\Messaging\Adapters\SMS\Textmagic;
|
use Utopia\Messaging\Adapter\Push\APNS;
|
||||||
use Utopia\Messaging\Adapters\SMS\Twilio;
|
use Utopia\Messaging\Adapter\Push\FCM;
|
||||||
use Utopia\Messaging\Adapters\SMS\Vonage;
|
use Utopia\Messaging\Adapter\SMS as SMSAdapter;
|
||||||
use Utopia\Messaging\Adapters\Push as PushAdapter;
|
use Utopia\Messaging\Adapter\SMS\Mock;
|
||||||
use Utopia\Messaging\Adapters\Push\APNS;
|
use Utopia\Messaging\Adapter\SMS\Msg91;
|
||||||
use Utopia\Messaging\Adapters\Push\FCM;
|
use Utopia\Messaging\Adapter\SMS\Telesign;
|
||||||
use Utopia\Messaging\Adapters\Email as EmailAdapter;
|
use Utopia\Messaging\Adapter\SMS\Textmagic;
|
||||||
use Utopia\Messaging\Adapters\Email\Mailgun;
|
use Utopia\Messaging\Adapter\SMS\Twilio;
|
||||||
use Utopia\Messaging\Adapters\Email\SendGrid;
|
use Utopia\Messaging\Adapter\SMS\Vonage;
|
||||||
use Utopia\Messaging\Messages\Email;
|
use Utopia\Messaging\Messages\Email;
|
||||||
use Utopia\Messaging\Messages\Push;
|
use Utopia\Messaging\Messages\Push;
|
||||||
use Utopia\Messaging\Messages\SMS;
|
use Utopia\Messaging\Messages\SMS;
|
||||||
|
use Utopia\Messaging\Response;
|
||||||
|
|
||||||
use function Swoole\Coroutine\batch;
|
use function Swoole\Coroutine\batch;
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ class Messaging extends Action
|
||||||
$payload = $message->getPayload() ?? [];
|
$payload = $message->getPayload() ?? [];
|
||||||
|
|
||||||
if (empty($payload)) {
|
if (empty($payload)) {
|
||||||
Console::error('Payload arg not found');
|
Console::error('Payload not found.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,14 +85,14 @@ class Messaging extends Action
|
||||||
$usersId = $message->getAttribute('users', []);
|
$usersId = $message->getAttribute('users', []);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Document[] $recipients
|
* @var Document[] $recipients
|
||||||
*/
|
*/
|
||||||
$recipients = [];
|
$recipients = [];
|
||||||
|
|
||||||
if (\count($topicsId) > 0) {
|
if (\count($topicsId) > 0) {
|
||||||
$topics = $dbForProject->find('topics', [Query::equal('$id', $topicsId)]);
|
$topics = $dbForProject->find('topics', [Query::equal('$id', $topicsId)]);
|
||||||
foreach ($topics as $topic) {
|
foreach ($topics as $topic) {
|
||||||
$targets = \array_filter($topic->getAttribute('targets'), fn (Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
|
$targets = \array_filter($topic->getAttribute('targets'), fn(Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
|
||||||
$recipients = \array_merge($recipients, $targets);
|
$recipients = \array_merge($recipients, $targets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +100,7 @@ class Messaging extends Action
|
||||||
if (\count($usersId) > 0) {
|
if (\count($usersId) > 0) {
|
||||||
$users = $dbForProject->find('users', [Query::equal('$id', $usersId)]);
|
$users = $dbForProject->find('users', [Query::equal('$id', $usersId)]);
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$targets = \array_filter($user->getAttribute('targets'), fn (Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
|
$targets = \array_filter($user->getAttribute('targets'), fn(Document $target) => $target->getAttribute('providerType') === $message->getAttribute('providerType'));
|
||||||
$recipients = \array_merge($recipients, $targets);
|
$recipients = \array_merge($recipients, $targets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,14 +116,16 @@ class Messaging extends Action
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<string, array<string>> $identifiersByProviderId
|
* @var array<string, array<string>> $identifiersByProviderId
|
||||||
*/
|
*/
|
||||||
$identifiersByProviderId = [];
|
$identifiersByProviderId = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Document[] $providers
|
* @var Document[] $providers
|
||||||
*/
|
*/
|
||||||
$providers = [];
|
$providers = [
|
||||||
|
$primaryProvider->getId() => $primaryProvider
|
||||||
|
];
|
||||||
foreach ($recipients as $recipient) {
|
foreach ($recipients as $recipient) {
|
||||||
$providerId = $recipient->getAttribute('providerId');
|
$providerId = $recipient->getAttribute('providerId');
|
||||||
|
|
||||||
|
@ -139,29 +142,28 @@ class Messaging extends Action
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array[] $results
|
* @var array[] $results
|
||||||
*/
|
*/
|
||||||
$results = batch(\array_map(function ($providerId) use ($identifiersByProviderId, $providers, $primaryProvider, $message, $dbForProject) {
|
$results = batch(\array_map(function ($providerId) use ($identifiersByProviderId, $providers, $primaryProvider, $message, $dbForProject) {
|
||||||
return function () use ($providerId, $identifiersByProviderId, $providers, $primaryProvider, $message, $dbForProject) {
|
return function () use ($providerId, $identifiersByProviderId, $providers, $primaryProvider, $message, $dbForProject) {
|
||||||
$provider = new Document();
|
if (\array_key_exists($providerId, $providers)) {
|
||||||
|
$provider = $providers[$providerId];
|
||||||
if ($primaryProvider->getId() === $providerId) {
|
|
||||||
$provider = $primaryProvider;
|
|
||||||
} else {
|
} else {
|
||||||
$provider = $dbForProject->getDocument('providers', $providerId, [Query::equal('enabled', [true])]);
|
$provider = $dbForProject->getDocument('providers', $providerId, [Query::equal('enabled', [true])]);
|
||||||
|
|
||||||
if ($provider->isEmpty()) {
|
if ($provider->isEmpty()) {
|
||||||
$provider = $primaryProvider;
|
$provider = $primaryProvider;
|
||||||
|
} else {
|
||||||
|
$providers[$providerId] = $provider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$providers[] = $provider;
|
|
||||||
$identifiers = $identifiersByProviderId[$providerId];
|
$identifiers = $identifiersByProviderId[$providerId];
|
||||||
|
|
||||||
$adapter = match ($provider->getAttribute('type')) {
|
$adapter = match ($provider->getAttribute('type')) {
|
||||||
MESSAGE_TYPE_SMS => $this->sms($provider),
|
MESSAGE_TYPE_SMS => $this->sms($provider),
|
||||||
MESSAGE_TYPE_PUSH => $this->push($provider),
|
MESSAGE_TYPE_PUSH => $this->push($provider),
|
||||||
MESSAGE_TYPE_EMAIL => $this->email($provider),
|
MESSAGE_TYPE_EMAIL => $this->email($provider),
|
||||||
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
|
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,8 +171,8 @@ class Messaging extends Action
|
||||||
$batches = \array_chunk($identifiers, $maxBatchSize);
|
$batches = \array_chunk($identifiers, $maxBatchSize);
|
||||||
$batchIndex = 0;
|
$batchIndex = 0;
|
||||||
|
|
||||||
$results = batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex) {
|
return batch(\array_map(function ($batch) use ($message, $provider, $adapter, $batchIndex, $dbForProject) {
|
||||||
return function () use ($batch, $message, $provider, $adapter, $batchIndex) {
|
return function () use ($batch, $message, $provider, $adapter, $batchIndex, $dbForProject) {
|
||||||
$deliveredTotal = 0;
|
$deliveredTotal = 0;
|
||||||
$deliveryErrors = [];
|
$deliveryErrors = [];
|
||||||
$messageData = clone $message;
|
$messageData = clone $message;
|
||||||
|
@ -179,13 +181,29 @@ class Messaging extends Action
|
||||||
$data = match ($provider->getAttribute('type')) {
|
$data = match ($provider->getAttribute('type')) {
|
||||||
MESSAGE_TYPE_SMS => $this->buildSMSMessage($messageData, $provider),
|
MESSAGE_TYPE_SMS => $this->buildSMSMessage($messageData, $provider),
|
||||||
MESSAGE_TYPE_PUSH => $this->buildPushMessage($messageData),
|
MESSAGE_TYPE_PUSH => $this->buildPushMessage($messageData),
|
||||||
MESSAGE_TYPE_EMAIL => $this->buildEmailMessage($messageData, $provider),
|
MESSAGE_TYPE_EMAIL => $this->buildEmailMessage($dbForProject, $messageData, $provider),
|
||||||
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
|
default => throw new Exception(Exception::PROVIDER_INCORRECT_TYPE)
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$adapter->send($data);
|
$response = new Response($provider->getAttribute('type'));
|
||||||
$deliveredTotal += \count($batch);
|
$response->fromArray($adapter->send($data));
|
||||||
|
|
||||||
|
$deliveredTotal += $response->getDeliveredTo();
|
||||||
|
$details[] = $response->getDetails();
|
||||||
|
foreach ($details as $detail) {
|
||||||
|
if ($detail['status'] === 'failure') {
|
||||||
|
$deliveryErrors[] = "Failed sending to target {$detail['recipient']} with error: {$detail['error']}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleting push targets when token has expired.
|
||||||
|
if ($detail['error'] === 'Expired device token.') {
|
||||||
|
$target = $dbForProject->findOne('targets', [Query::equal('identifier', [$detail['recipient']])]);
|
||||||
|
if ($target instanceof Document && !$target->isEmpty()) {
|
||||||
|
$dbForProject->deleteDocument('targets', $target->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage();
|
$deliveryErrors[] = 'Failed sending to targets ' . $batchIndex + 1 . '-' . \count($batch) . ' with error: ' . $e->getMessage();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -197,8 +215,6 @@ class Messaging extends Action
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, $batches));
|
}, $batches));
|
||||||
|
|
||||||
return $results;
|
|
||||||
};
|
};
|
||||||
}, \array_keys($identifiersByProviderId)));
|
}, \array_keys($identifiersByProviderId)));
|
||||||
|
|
||||||
|
@ -313,7 +329,7 @@ class Messaging extends Action
|
||||||
'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']),
|
'twilio' => new Twilio($credentials['accountSid'], $credentials['authToken']),
|
||||||
'textmagic' => new Textmagic($credentials['username'], $credentials['apiKey']),
|
'textmagic' => new Textmagic($credentials['username'], $credentials['apiKey']),
|
||||||
'telesign' => new Telesign($credentials['username'], $credentials['password']),
|
'telesign' => new Telesign($credentials['username'], $credentials['password']),
|
||||||
'msg91' => new Msg91($credentials['senderId'], $credentials['authKey']),
|
'msg91' => new Msg91($credentials['senderId'], $credentials['authKey'], $credentials['templateId']),
|
||||||
'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']),
|
'vonage' => new Vonage($credentials['apiKey'], $credentials['apiSecret']),
|
||||||
default => null
|
default => null
|
||||||
};
|
};
|
||||||
|
@ -323,6 +339,7 @@ class Messaging extends Action
|
||||||
{
|
{
|
||||||
$credentials = $provider->getAttribute('credentials');
|
$credentials = $provider->getAttribute('credentials');
|
||||||
return match ($provider->getAttribute('provider')) {
|
return match ($provider->getAttribute('provider')) {
|
||||||
|
'mock' => new Mock('username', 'password'),
|
||||||
'apns' => new APNS(
|
'apns' => new APNS(
|
||||||
$credentials['authKey'],
|
$credentials['authKey'],
|
||||||
$credentials['authKeyId'],
|
$credentials['authKeyId'],
|
||||||
|
@ -330,7 +347,7 @@ class Messaging extends Action
|
||||||
$credentials['bundleId'],
|
$credentials['bundleId'],
|
||||||
$credentials['endpoint']
|
$credentials['endpoint']
|
||||||
),
|
),
|
||||||
'fcm' => new FCM($credentials['serverKey']),
|
'fcm' => new FCM($credentials['serviceAccountJSON']),
|
||||||
default => null
|
default => null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -339,21 +356,51 @@ class Messaging extends Action
|
||||||
{
|
{
|
||||||
$credentials = $provider->getAttribute('credentials');
|
$credentials = $provider->getAttribute('credentials');
|
||||||
return match ($provider->getAttribute('provider')) {
|
return match ($provider->getAttribute('provider')) {
|
||||||
|
'mock' => new Mock('username', 'password'),
|
||||||
'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']),
|
'mailgun' => new Mailgun($credentials['apiKey'], $credentials['domain'], $credentials['isEuRegion']),
|
||||||
'sendgrid' => new SendGrid($credentials['apiKey']),
|
'sendgrid' => new Sendgrid($credentials['apiKey']),
|
||||||
default => null
|
default => null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildEmailMessage(Document $message, Document $provider): Email
|
private function buildEmailMessage(Database $dbForProject, Document $message, Document $provider): Email
|
||||||
{
|
{
|
||||||
$from = $provider['options']['from'];
|
$fromName = $provider['options']['fromName'];
|
||||||
$to = $message['to'];
|
$fromEmail = $provider['options']['fromEmail'];
|
||||||
$subject = $message['data']['subject'];
|
$replyToEmail = null;
|
||||||
$content = $message['data']['content'];
|
$replyToName = null;
|
||||||
$html = $message['data']['html'];
|
|
||||||
|
|
||||||
return new Email($to, $subject, $content, $from, null, $html);
|
if (isset($provider['options']['replyToName']) && isset($provider['options']['replyToEmail'])) {
|
||||||
|
$replyToName = $provider['options']['replyToName'];
|
||||||
|
$replyToEmail = $provider['options']['replyToEmail'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $message['data'] ?? [];
|
||||||
|
$ccTargets = $data['cc'] ?? [];
|
||||||
|
$bccTargets = $data['bcc'] ?? [];
|
||||||
|
$cc = [];
|
||||||
|
$bcc = [];
|
||||||
|
|
||||||
|
if (\count($ccTargets) > 0) {
|
||||||
|
$ccTargets = $dbForProject->find('targets', [Query::equal('identifier', $ccTargets)]);
|
||||||
|
foreach ($ccTargets as $ccTarget) {
|
||||||
|
$cc[] = ['email' => $ccTarget['identifier']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\count($bccTargets) > 0) {
|
||||||
|
$bccTargets = $dbForProject->find('targets', [Query::equal('identifier', $bccTargets)]);
|
||||||
|
foreach ($bccTargets as $bccTarget) {
|
||||||
|
$bcc[] = ['email' => $bccTarget['identifier']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$to = $message['to'];
|
||||||
|
$subject = $data['subject'];
|
||||||
|
$content = $data['content'];
|
||||||
|
$html = $data['html'];
|
||||||
|
|
||||||
|
return new Email($to, $subject, $content, $fromName, $fromEmail, $replyToName, $replyToEmail, $cc, $bcc, null, $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildSMSMessage(Document $message, Document $provider): SMS
|
private function buildSMSMessage(Document $message, Document $provider): SMS
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Topics extends Base
|
||||||
public const ALLOWED_ATTRIBUTES = [
|
public const ALLOWED_ATTRIBUTES = [
|
||||||
'name',
|
'name',
|
||||||
'description',
|
'description',
|
||||||
|
'total'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -72,6 +72,7 @@ class Executor
|
||||||
) {
|
) {
|
||||||
$runtimeId = "$projectId-$deploymentId-build";
|
$runtimeId = "$projectId-$deploymentId-build";
|
||||||
$route = "/runtimes";
|
$route = "/runtimes";
|
||||||
|
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
|
||||||
$params = [
|
$params = [
|
||||||
'runtimeId' => $runtimeId,
|
'runtimeId' => $runtimeId,
|
||||||
'source' => $source,
|
'source' => $source,
|
||||||
|
@ -84,10 +85,9 @@ class Executor
|
||||||
'cpus' => $this->cpus,
|
'cpus' => $this->cpus,
|
||||||
'memory' => $this->memory,
|
'memory' => $this->memory,
|
||||||
'version' => $version,
|
'version' => $version,
|
||||||
|
'timeout' => $timeout,
|
||||||
];
|
];
|
||||||
|
|
||||||
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
|
|
||||||
|
|
||||||
$response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout);
|
$response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout);
|
||||||
|
|
||||||
$status = $response['headers']['status-code'];
|
$status = $response['headers']['status-code'];
|
||||||
|
@ -111,7 +111,7 @@ class Executor
|
||||||
string $projectId,
|
string $projectId,
|
||||||
callable $callback
|
callable $callback
|
||||||
) {
|
) {
|
||||||
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
|
$timeout = (int) App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900);
|
||||||
|
|
||||||
$runtimeId = "$projectId-$deploymentId-build";
|
$runtimeId = "$projectId-$deploymentId-build";
|
||||||
$route = "/runtimes/{$runtimeId}/logs";
|
$route = "/runtimes/{$runtimeId}/logs";
|
||||||
|
|
|
@ -1790,8 +1790,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$CREATE_MAILGUN_PROVIDER:
|
case self::$CREATE_MAILGUN_PROVIDER:
|
||||||
return 'mutation createMailgunProvider($providerId: String!, $name: String!, $domain: String!, $apiKey: String!, $from: String!, $isEuRegion: Boolean!) {
|
return 'mutation createMailgunProvider($providerId: String!, $name: String!, $domain: String!, $apiKey: String!, $fromName: String!, $fromEmail: String!, $isEuRegion: Boolean!, $replyToName: String, $replyToEmail: String) {
|
||||||
messagingCreateMailgunProvider(providerId: $providerId, name: $name, domain: $domain, apiKey: $apiKey, from: $from, isEuRegion: $isEuRegion) {
|
messagingCreateMailgunProvider(providerId: $providerId, name: $name, domain: $domain, apiKey: $apiKey, fromName: $fromName, fromEmail: $fromEmail, isEuRegion: $isEuRegion, replyToName: $replyToName, replyToEmail: $replyToEmail) {
|
||||||
_id
|
_id
|
||||||
name
|
name
|
||||||
provider
|
provider
|
||||||
|
@ -1800,8 +1800,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$CREATE_SENDGRID_PROVIDER:
|
case self::$CREATE_SENDGRID_PROVIDER:
|
||||||
return 'mutation createSendgridProvider($providerId: String!, $name: String!, $from: String!, $apiKey: String!) {
|
return 'mutation createSendgridProvider($providerId: String!, $name: String!, $fromName: String!, $fromEmail: String!, $apiKey: String!, $replyToName: String, $replyToEmail: String) {
|
||||||
messagingCreateSendgridProvider(providerId: $providerId, name: $name, from: $from, apiKey: $apiKey) {
|
messagingCreateSendgridProvider(providerId: $providerId, name: $name, fromName: $fromName, fromEmail: $fromEmail, apiKey: $apiKey, replyToName: $replyToName, replyToEmail: $replyToEmail) {
|
||||||
_id
|
_id
|
||||||
name
|
name
|
||||||
provider
|
provider
|
||||||
|
@ -1860,8 +1860,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$CREATE_FCM_PROVIDER:
|
case self::$CREATE_FCM_PROVIDER:
|
||||||
return 'mutation createFcmProvider($providerId: String!, $name: String!, $serverKey: String!) {
|
return 'mutation createFcmProvider($providerId: String!, $name: String!, $serviceAccountJSON: Json) {
|
||||||
messagingCreateFcmProvider(providerId: $providerId, name: $name, serverKey: $serverKey) {
|
messagingCreateFcmProvider(providerId: $providerId, name: $name, serviceAccountJSON: $serviceAccountJSON) {
|
||||||
_id
|
_id
|
||||||
name
|
name
|
||||||
provider
|
provider
|
||||||
|
@ -1904,8 +1904,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$UPDATE_MAILGUN_PROVIDER:
|
case self::$UPDATE_MAILGUN_PROVIDER:
|
||||||
return 'mutation updateMailgunProvider($providerId: String!, $name: String!, $domain: String!, $apiKey: String!, $isEuRegion: Boolean, $enabled: Boolean) {
|
return 'mutation updateMailgunProvider($providerId: String!, $name: String!, $domain: String!, $apiKey: String!, $isEuRegion: Boolean, $enabled: Boolean, $fromName: String, $fromEmail: String) {
|
||||||
messagingUpdateMailgunProvider(providerId: $providerId, name: $name, domain: $domain, apiKey: $apiKey, isEuRegion: $isEuRegion, enabled: $enabled) {
|
messagingUpdateMailgunProvider(providerId: $providerId, name: $name, domain: $domain, apiKey: $apiKey, isEuRegion: $isEuRegion, enabled: $enabled, fromName: $fromName, fromEmail: $fromEmail) {
|
||||||
_id
|
_id
|
||||||
name
|
name
|
||||||
provider
|
provider
|
||||||
|
@ -1914,8 +1914,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$UPDATE_SENDGRID_PROVIDER:
|
case self::$UPDATE_SENDGRID_PROVIDER:
|
||||||
return 'mutation messagingUpdateSendgridProvider($providerId: String!, $name: String!, $apiKey: String!) {
|
return 'mutation messagingUpdateSendgridProvider($providerId: String!, $name: String!, $apiKey: String!, $enabled: Boolean, $fromName: String, $fromEmail: String) {
|
||||||
messagingUpdateSendgridProvider(providerId: $providerId, name: $name, apiKey: $apiKey) {
|
messagingUpdateSendgridProvider(providerId: $providerId, name: $name, apiKey: $apiKey, enabled: $enabled, fromName: $fromName, fromEmail: $fromEmail) {
|
||||||
_id
|
_id
|
||||||
name
|
name
|
||||||
provider
|
provider
|
||||||
|
@ -1974,8 +1974,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$UPDATE_FCM_PROVIDER:
|
case self::$UPDATE_FCM_PROVIDER:
|
||||||
return 'mutation updateFcmProvider($providerId: String!, $name: String!, $serverKey: String!) {
|
return 'mutation updateFcmProvider($providerId: String!, $name: String!, $serviceAccountJSON: Json) {
|
||||||
messagingUpdateFcmProvider(providerId: $providerId, name: $name, serverKey: $serverKey) {
|
messagingUpdateFcmProvider(providerId: $providerId, name: $name, serviceAccountJSON: $serviceAccountJSON) {
|
||||||
_id
|
_id
|
||||||
name
|
name
|
||||||
provider
|
provider
|
||||||
|
@ -2098,8 +2098,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$CREATE_EMAIL:
|
case self::$CREATE_EMAIL:
|
||||||
return 'mutation createEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String!, $content: String!, $status: String, $description: String, $html: Boolean, $scheduledAt: String) {
|
return 'mutation createEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String!, $content: String!, $status: String, $description: String, $html: Boolean, $cc: [String], $bcc: [String], $scheduledAt: String) {
|
||||||
messagingCreateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, scheduledAt: $scheduledAt) {
|
messagingCreateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, cc: $cc, bcc: $bcc, scheduledAt: $scheduledAt) {
|
||||||
_id
|
_id
|
||||||
topics
|
topics
|
||||||
users
|
users
|
||||||
|
@ -2178,8 +2178,8 @@ trait Base
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
case self::$UPDATE_EMAIL:
|
case self::$UPDATE_EMAIL:
|
||||||
return 'mutation updateEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String, $content: String, $status: String, $description: String, $html: Boolean, $scheduledAt: String) {
|
return 'mutation updateEmail($messageId: String!, $topics: [String!], $users: [String!], $targets: [String!], $subject: String, $content: String, $status: String, $description: String, $html: Boolean, $cc: [String], $bcc: [String], $scheduledAt: String) {
|
||||||
messagingUpdateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, scheduledAt: $scheduledAt) {
|
messagingUpdateEmail(messageId: $messageId, topics: $topics, users: $users, targets: $targets, subject: $subject, content: $content, status: $status, description: $description, html: $html, cc: $cc, bcc: $bcc, scheduledAt: $scheduledAt) {
|
||||||
_id
|
_id
|
||||||
topics
|
topics
|
||||||
users
|
users
|
||||||
|
|
|
@ -23,14 +23,16 @@ class MessagingTest extends Scope
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'Sengrid1',
|
'name' => 'Sengrid1',
|
||||||
'apiKey' => 'my-apikey',
|
'apiKey' => 'my-apikey',
|
||||||
'from' => 'sender-email@my-domain.com',
|
'fromName' => 'Sender Name',
|
||||||
|
'fromEmail' => 'sender-email@my-domain.com',
|
||||||
],
|
],
|
||||||
'Mailgun' => [
|
'Mailgun' => [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'Mailgun1',
|
'name' => 'Mailgun1',
|
||||||
'apiKey' => 'my-apikey',
|
'apiKey' => 'my-apikey',
|
||||||
'domain' => 'my-domain',
|
'domain' => 'my-domain',
|
||||||
'from' => 'sender-email@my-domain.com',
|
'fromName' => 'Sender Name',
|
||||||
|
'fromEmail' => 'sender-email@my-domain.com',
|
||||||
'isEuRegion' => false,
|
'isEuRegion' => false,
|
||||||
],
|
],
|
||||||
'Twilio' => [
|
'Twilio' => [
|
||||||
|
@ -71,7 +73,12 @@ class MessagingTest extends Scope
|
||||||
'Fcm' => [
|
'Fcm' => [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'FCM1',
|
'name' => 'FCM1',
|
||||||
'serverKey' => 'my-serverkey',
|
'serviceAccountJSON' => [
|
||||||
|
'type' => 'service_account',
|
||||||
|
"project_id" => "test-project",
|
||||||
|
"private_key_id" => "test-private-key-id",
|
||||||
|
"private_key" => "test-private-key",
|
||||||
|
]
|
||||||
],
|
],
|
||||||
'Apns' => [
|
'Apns' => [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
|
@ -97,6 +104,7 @@ class MessagingTest extends Scope
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
]), $graphQLPayload);
|
]), $graphQLPayload);
|
||||||
|
|
||||||
\array_push($providers, $response['body']['data']['messagingCreate' . $key . 'Provider']);
|
\array_push($providers, $response['body']['data']['messagingCreate' . $key . 'Provider']);
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertEquals($providersParams[$key]['name'], $response['body']['data']['messagingCreate' . $key . 'Provider']['name']);
|
$this->assertEquals($providersParams[$key]['name'], $response['body']['data']['messagingCreate' . $key . 'Provider']['name']);
|
||||||
|
@ -155,7 +163,12 @@ class MessagingTest extends Scope
|
||||||
'Fcm' => [
|
'Fcm' => [
|
||||||
'providerId' => $providers[7]['_id'],
|
'providerId' => $providers[7]['_id'],
|
||||||
'name' => 'FCM2',
|
'name' => 'FCM2',
|
||||||
'serverKey' => 'my-serverkey',
|
'serviceAccountJSON' => [
|
||||||
|
'type' => 'service_account',
|
||||||
|
'project_id' => 'test-project',
|
||||||
|
'private_key_id' => 'test-project-id',
|
||||||
|
'private_key' => "test-private-key",
|
||||||
|
]
|
||||||
],
|
],
|
||||||
'Apns' => [
|
'Apns' => [
|
||||||
'providerId' => $providers[8]['_id'],
|
'providerId' => $providers[8]['_id'],
|
||||||
|
@ -374,7 +387,8 @@ class MessagingTest extends Scope
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'Sengrid1',
|
'name' => 'Sengrid1',
|
||||||
'apiKey' => 'my-apikey',
|
'apiKey' => 'my-apikey',
|
||||||
'from' => 'sender-email@my-domain.com',
|
'fromName' => 'Sender',
|
||||||
|
'fromEmail' => 'sender-email@my-domain.com',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
$query = $this->getQuery(self::$CREATE_SENDGRID_PROVIDER);
|
$query = $this->getQuery(self::$CREATE_SENDGRID_PROVIDER);
|
||||||
|
@ -543,7 +557,8 @@ class MessagingTest extends Scope
|
||||||
|
|
||||||
$emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'));
|
$emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'));
|
||||||
$to = $emailDSN->getParam('to');
|
$to = $emailDSN->getParam('to');
|
||||||
$from = $emailDSN->getParam('from');
|
$fromName = $emailDSN->getParam('fromName');
|
||||||
|
$fromEmail = $emailDSN->getParam('fromEmail');
|
||||||
$isEuRegion = $emailDSN->getParam('isEuRegion');
|
$isEuRegion = $emailDSN->getParam('isEuRegion');
|
||||||
$apiKey = $emailDSN->getPassword();
|
$apiKey = $emailDSN->getPassword();
|
||||||
$domain = $emailDSN->getUser();
|
$domain = $emailDSN->getUser();
|
||||||
|
@ -560,7 +575,8 @@ class MessagingTest extends Scope
|
||||||
'name' => 'Mailgun1',
|
'name' => 'Mailgun1',
|
||||||
'apiKey' => $apiKey,
|
'apiKey' => $apiKey,
|
||||||
'domain' => $domain,
|
'domain' => $domain,
|
||||||
'from' => $from,
|
'fromName' => $fromName,
|
||||||
|
'fromEmail' => $fromEmail,
|
||||||
'isEuRegion' => filter_var($isEuRegion, FILTER_VALIDATE_BOOLEAN),
|
'isEuRegion' => filter_var($isEuRegion, FILTER_VALIDATE_BOOLEAN),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -956,9 +972,9 @@ class MessagingTest extends Scope
|
||||||
|
|
||||||
$pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'));
|
$pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'));
|
||||||
$to = $pushDSN->getParam('to');
|
$to = $pushDSN->getParam('to');
|
||||||
$serverKey = $pushDSN->getPassword();
|
$serviceAccountJSON = $pushDSN->getParam('serviceAccountJSON');
|
||||||
|
|
||||||
if (empty($to) || empty($serverKey)) {
|
if (empty($to) || empty($serviceAccountJSON)) {
|
||||||
$this->markTestSkipped('Push provider not configured');
|
$this->markTestSkipped('Push provider not configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -968,7 +984,12 @@ class MessagingTest extends Scope
|
||||||
'variables' => [
|
'variables' => [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'FCM1',
|
'name' => 'FCM1',
|
||||||
'serverKey' => $serverKey,
|
'serviceAccountJSON' => [
|
||||||
|
'type' => 'service_account',
|
||||||
|
"project_id" => "test-project",
|
||||||
|
"private_key_id" => "test-private-key-id",
|
||||||
|
"private_key" => "test-private-key",
|
||||||
|
]
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$provider = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
$provider = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||||
|
|
|
@ -60,7 +60,8 @@ class UsersTest extends Scope
|
||||||
'name' => 'Mailgun1',
|
'name' => 'Mailgun1',
|
||||||
'apiKey' => 'api-key',
|
'apiKey' => 'api-key',
|
||||||
'domain' => 'domain',
|
'domain' => 'domain',
|
||||||
'from' => 'from@domain.com',
|
'fromName' => 'sender name',
|
||||||
|
'fromEmail' => 'from@domain.com',
|
||||||
'isEuRegion' => false,
|
'isEuRegion' => false,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Messaging;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Database\Helpers\ID;
|
use Utopia\Database\Helpers\ID;
|
||||||
|
use Utopia\Database\Query;
|
||||||
use Utopia\DSN\DSN;
|
use Utopia\DSN\DSN;
|
||||||
|
|
||||||
trait MessagingBase
|
trait MessagingBase
|
||||||
|
@ -23,7 +24,8 @@ trait MessagingBase
|
||||||
'name' => 'Mailgun1',
|
'name' => 'Mailgun1',
|
||||||
'apiKey' => 'my-apikey',
|
'apiKey' => 'my-apikey',
|
||||||
'domain' => 'my-domain',
|
'domain' => 'my-domain',
|
||||||
'from' => 'sender-email@my-domain.com',
|
'fromName' => 'sender name',
|
||||||
|
'fromEmail' => 'sender-email@my-domain.com',
|
||||||
'isEuRegion' => false,
|
'isEuRegion' => false,
|
||||||
],
|
],
|
||||||
'twilio' => [
|
'twilio' => [
|
||||||
|
@ -64,7 +66,12 @@ trait MessagingBase
|
||||||
'fcm' => [
|
'fcm' => [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'FCM1',
|
'name' => 'FCM1',
|
||||||
'serverKey' => 'my-serverkey',
|
'serviceAccountJSON' => [
|
||||||
|
'type' => 'service_account',
|
||||||
|
"project_id" => "test-project",
|
||||||
|
"private_key_id" => "test-private-key-id",
|
||||||
|
"private_key" => "test-private-key",
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'apns' => [
|
'apns' => [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
|
@ -84,6 +91,7 @@ trait MessagingBase
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
]), $providersParams[$key]);
|
]), $providersParams[$key]);
|
||||||
|
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertEquals($providersParams[$key]['name'], $response['body']['name']);
|
$this->assertEquals($providersParams[$key]['name'], $response['body']['name']);
|
||||||
\array_push($providers, $response['body']);
|
\array_push($providers, $response['body']);
|
||||||
|
@ -134,7 +142,12 @@ trait MessagingBase
|
||||||
],
|
],
|
||||||
'fcm' => [
|
'fcm' => [
|
||||||
'name' => 'FCM2',
|
'name' => 'FCM2',
|
||||||
'serverKey' => 'my-serverkey',
|
'serviceAccountJSON' => [
|
||||||
|
'type' => 'service_account',
|
||||||
|
"project_id" => "test-project",
|
||||||
|
"private_key_id" => "test-private-key-id",
|
||||||
|
"private_key" => "test-private-key",
|
||||||
|
]
|
||||||
],
|
],
|
||||||
'apns' => [
|
'apns' => [
|
||||||
'name' => 'APNS2',
|
'name' => 'APNS2',
|
||||||
|
@ -161,11 +174,11 @@ trait MessagingBase
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
], [
|
], [
|
||||||
'name' => 'Mailgun2',
|
'name' => 'Mailgun2',
|
||||||
'apiKey' => 'my-apikey',
|
'apiKey' => 'my-apikey',
|
||||||
'domain' => 'my-domain',
|
'domain' => 'my-domain',
|
||||||
'isEuRegion' => true,
|
'isEuRegion' => true,
|
||||||
'enabled' => false,
|
'enabled' => false,
|
||||||
]);
|
]);
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertEquals('Mailgun2', $response['body']['name']);
|
$this->assertEquals('Mailgun2', $response['body']['name']);
|
||||||
|
@ -229,7 +242,6 @@ trait MessagingBase
|
||||||
], [
|
], [
|
||||||
'topicId' => ID::unique(),
|
'topicId' => ID::unique(),
|
||||||
'name' => 'my-app',
|
'name' => 'my-app',
|
||||||
'description' => 'web app'
|
|
||||||
]);
|
]);
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertEquals('my-app', $response['body']['name']);
|
$this->assertEquals('my-app', $response['body']['name']);
|
||||||
|
@ -272,6 +284,32 @@ trait MessagingBase
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertEquals(1, \count($response['body']['topics']));
|
$this->assertEquals(1, \count($response['body']['topics']));
|
||||||
|
|
||||||
|
$response = $this->client->call(Client::METHOD_GET, '/messaging/topics', [
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
|
], [
|
||||||
|
'queries' => [
|
||||||
|
'equal("total", [0])'
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
$this->assertEquals(1, \count($response['body']['topics']));
|
||||||
|
|
||||||
|
$response = $this->client->call(Client::METHOD_GET, '/messaging/topics', [
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
|
], [
|
||||||
|
'queries' => [
|
||||||
|
'greaterThan("total", 0)'
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
$this->assertEquals(0, \count($response['body']['topics']));
|
||||||
|
|
||||||
return $topicId;
|
return $topicId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,17 +590,16 @@ trait MessagingBase
|
||||||
|
|
||||||
$emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'));
|
$emailDSN = new DSN(App::getEnv('_APP_MESSAGE_EMAIL_TEST_DSN'));
|
||||||
$to = $emailDSN->getParam('to');
|
$to = $emailDSN->getParam('to');
|
||||||
$from = $emailDSN->getParam('from');
|
$fromName = $emailDSN->getParam('fromName');
|
||||||
$isEuRegion = $emailDSN->getParam('isEuRegion');
|
$fromEmail = $emailDSN->getParam('fromEmail');
|
||||||
$apiKey = $emailDSN->getPassword();
|
$apiKey = $emailDSN->getPassword();
|
||||||
$domain = $emailDSN->getUser();
|
|
||||||
|
|
||||||
if (empty($to) || empty($from) || empty($apiKey) || empty($domain) || empty($isEuRegion)) {
|
if (empty($to) || empty($apiKey)) {
|
||||||
$this->markTestSkipped('Email provider not configured');
|
$this->markTestSkipped('Email provider not configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create provider
|
// Create provider
|
||||||
$provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/mailgun', \array_merge([
|
$provider = $this->client->call(Client::METHOD_POST, '/messaging/providers/sendgrid', \array_merge([
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
|
@ -570,9 +607,8 @@ trait MessagingBase
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'Mailgun-provider',
|
'name' => 'Mailgun-provider',
|
||||||
'apiKey' => $apiKey,
|
'apiKey' => $apiKey,
|
||||||
'domain' => $domain,
|
'fromName' => $fromName,
|
||||||
'isEuRegion' => filter_var($isEuRegion, FILTER_VALIDATE_BOOLEAN),
|
'fromEmail' => $fromEmail
|
||||||
'from' => $from
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals(201, $provider['headers']['status-code']);
|
$this->assertEquals(201, $provider['headers']['status-code']);
|
||||||
|
@ -604,27 +640,13 @@ trait MessagingBase
|
||||||
|
|
||||||
$this->assertEquals(201, $user['headers']['status-code']);
|
$this->assertEquals(201, $user['headers']['status-code']);
|
||||||
|
|
||||||
// Create Target
|
|
||||||
$target = $this->client->call(Client::METHOD_POST, '/users/' . $user['body']['$id'] . '/targets', [
|
|
||||||
'content-type' => 'application/json',
|
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
|
||||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
|
||||||
], [
|
|
||||||
'targetId' => ID::unique(),
|
|
||||||
'providerType' => 'email',
|
|
||||||
'providerId' => $provider['body']['$id'],
|
|
||||||
'identifier' => $to,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertEquals(201, $target['headers']['status-code']);
|
|
||||||
|
|
||||||
// Create Subscriber
|
// Create Subscriber
|
||||||
$subscriber = $this->client->call(Client::METHOD_POST, '/messaging/topics/' . $topic['body']['$id'] . '/subscribers', \array_merge([
|
$subscriber = $this->client->call(Client::METHOD_POST, '/messaging/topics/' . $topic['body']['$id'] . '/subscribers', \array_merge([
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
'subscriberId' => ID::unique(),
|
'subscriberId' => ID::unique(),
|
||||||
'targetId' => $target['body']['$id'],
|
'targetId' => $user['body']['targets'][0]['$id'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals(201, $subscriber['headers']['status-code']);
|
$this->assertEquals(201, $subscriber['headers']['status-code']);
|
||||||
|
@ -637,13 +659,13 @@ trait MessagingBase
|
||||||
], [
|
], [
|
||||||
'messageId' => ID::unique(),
|
'messageId' => ID::unique(),
|
||||||
'topics' => [$topic['body']['$id']],
|
'topics' => [$topic['body']['$id']],
|
||||||
'subject' => 'Khali beats Undertaker',
|
'subject' => 'New blog post',
|
||||||
'content' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
'content' => 'Check out the new blog post at http://localhost',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals(201, $email['headers']['status-code']);
|
$this->assertEquals(201, $email['headers']['status-code']);
|
||||||
|
|
||||||
\sleep(5);
|
\sleep(2);
|
||||||
|
|
||||||
$message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $email['body']['$id'], [
|
$message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $email['body']['$id'], [
|
||||||
'origin' => 'http://localhost',
|
'origin' => 'http://localhost',
|
||||||
|
@ -662,7 +684,7 @@ trait MessagingBase
|
||||||
/**
|
/**
|
||||||
* @depends testSendEmail
|
* @depends testSendEmail
|
||||||
*/
|
*/
|
||||||
public function testUpdateEmail(array $email)
|
public function testUpdateEmail(array $email): void
|
||||||
{
|
{
|
||||||
$message = $this->client->call(Client::METHOD_PATCH, '/messaging/messages/email/' . $email['body']['$id'], [
|
$message = $this->client->call(Client::METHOD_PATCH, '/messaging/messages/email/' . $email['body']['$id'], [
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
|
@ -721,8 +743,8 @@ trait MessagingBase
|
||||||
$smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'));
|
$smsDSN = new DSN(App::getEnv('_APP_MESSAGE_SMS_TEST_DSN'));
|
||||||
$to = $smsDSN->getParam('to');
|
$to = $smsDSN->getParam('to');
|
||||||
$from = $smsDSN->getParam('from');
|
$from = $smsDSN->getParam('from');
|
||||||
$authKey = $smsDSN->getPassword();
|
|
||||||
$senderId = $smsDSN->getUser();
|
$senderId = $smsDSN->getUser();
|
||||||
|
$authKey = $smsDSN->getPassword();
|
||||||
|
|
||||||
if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) {
|
if (empty($to) || empty($from) || empty($senderId) || empty($authKey)) {
|
||||||
$this->markTestSkipped('SMS provider not configured');
|
$this->markTestSkipped('SMS provider not configured');
|
||||||
|
@ -735,7 +757,7 @@ trait MessagingBase
|
||||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||||
]), [
|
]), [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'Msg91-1',
|
'name' => 'Msg91Sender',
|
||||||
'senderId' => $senderId,
|
'senderId' => $senderId,
|
||||||
'authKey' => $authKey,
|
'authKey' => $authKey,
|
||||||
'from' => $from
|
'from' => $from
|
||||||
|
@ -847,7 +869,7 @@ trait MessagingBase
|
||||||
'messageId' => ID::unique(),
|
'messageId' => ID::unique(),
|
||||||
'status' => 'draft',
|
'status' => 'draft',
|
||||||
'topics' => [$sms['body']['topics'][0]],
|
'topics' => [$sms['body']['topics'][0]],
|
||||||
'content' => '047487',
|
'content' => 'Your OTP code is 123456',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals(201, $sms['headers']['status-code']);
|
$this->assertEquals(201, $sms['headers']['status-code']);
|
||||||
|
@ -862,7 +884,7 @@ trait MessagingBase
|
||||||
|
|
||||||
$this->assertEquals(200, $sms['headers']['status-code']);
|
$this->assertEquals(200, $sms['headers']['status-code']);
|
||||||
|
|
||||||
\sleep(5);
|
\sleep(2);
|
||||||
|
|
||||||
$message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $sms['body']['$id'], [
|
$message = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $sms['body']['$id'], [
|
||||||
'origin' => 'http://localhost',
|
'origin' => 'http://localhost',
|
||||||
|
@ -882,11 +904,11 @@ trait MessagingBase
|
||||||
$this->markTestSkipped('Push DSN empty');
|
$this->markTestSkipped('Push DSN empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
$pushDSN = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'));
|
$dsn = new DSN(App::getEnv('_APP_MESSAGE_PUSH_TEST_DSN'));
|
||||||
$to = $pushDSN->getParam('to');
|
$to = $dsn->getParam('to');
|
||||||
$serverKey = $pushDSN->getPassword();
|
$serviceAccountJSON = $dsn->getParam('serviceAccountJSON');
|
||||||
|
|
||||||
if (empty($to) || empty($serverKey)) {
|
if (empty($to) || empty($serviceAccountJSON)) {
|
||||||
$this->markTestSkipped('Push provider not configured');
|
$this->markTestSkipped('Push provider not configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,7 +920,7 @@ trait MessagingBase
|
||||||
]), [
|
]), [
|
||||||
'providerId' => ID::unique(),
|
'providerId' => ID::unique(),
|
||||||
'name' => 'FCM-1',
|
'name' => 'FCM-1',
|
||||||
'serverKey' => $serverKey,
|
'serviceAccountJSON' => $serviceAccountJSON,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals(201, $provider['headers']['status-code']);
|
$this->assertEquals(201, $provider['headers']['status-code']);
|
||||||
|
|
|
@ -1661,7 +1661,6 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
|
|
||||||
foreach ($response['body'] as $key => $value) {
|
foreach ($response['body'] as $key => $value) {
|
||||||
if (\preg_match($pattern, $key)) {
|
if (\preg_match($pattern, $key)) {
|
||||||
\var_dump('Matched key: ' . $key);
|
|
||||||
$matches[$key] = $value;
|
$matches[$key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue