From f6f8816e2b19f2c567d397707e1d22c8ba75e425 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Sat, 17 Feb 2024 11:29:49 +0000 Subject: [PATCH 01/33] Migration Fixes --- app/init.php | 2 +- composer.lock | 10 ++--- src/Appwrite/Migration/Version/V20.php | 53 ++++++++++++-------------- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/app/init.php b/app/init.php index db4fe4d669..528ecdf777 100644 --- a/app/init.php +++ b/app/init.php @@ -113,7 +113,7 @@ const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours const APP_USER_ACCCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 329; -const APP_VERSION_STABLE = '1.4.13'; +const APP_VERSION_STABLE = '1.5.0'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/composer.lock b/composer.lock index 3956a87327..86c9472447 100644 --- a/composer.lock +++ b/composer.lock @@ -5019,16 +5019,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.8.1", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "14f5fff1e64118595db5408e946f3a22c75807f7" + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7", - "reference": "14f5fff1e64118595db5408e946f3a22c75807f7", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b", + "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b", "shasum": "" }, "require": { @@ -5095,7 +5095,7 @@ "type": "open_collective" } ], - "time": "2024-01-11T20:47:48+00:00" + "time": "2024-02-16T15:06:51+00:00" }, { "name": "swoole/ide-helper", diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 0e7434c56c..abc2bdac8e 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -30,8 +30,8 @@ class V20 extends Migration foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) { Database::addFilter( $name, - fn() => null, - fn() => [] + fn () => null, + fn () => [] ); } @@ -47,14 +47,16 @@ class V20 extends Migration Console::info('Migrating Collections'); $this->migrateCollections(); - Console::info('Migrating Functions'); - $this->migrateFunctions(); + if ($this->project->getInternalId() !== 'console') { + Console::info('Migrating Functions'); + $this->migrateFunctions(); - Console::info('Migrating Databases'); - $this->migrateDatabases(); + Console::info('Migrating Databases'); + $this->migrateDatabases(); - Console::info('Migrating Buckets'); - $this->migrateBuckets(); + Console::info('Migrating Buckets'); + $this->migrateBuckets(); + } Console::info('Migrating Documents'); $this->forEachDocument([$this, 'fixDocument']); @@ -75,25 +77,23 @@ class V20 extends Migration }; // Support database array type migration (user collections) - foreach ( - $this->documentsIterator('attributes', [ + if ($collectionType === 'projects') { + foreach ($this->documentsIterator('attributes', [ Query::equal('array', [true]), - ]) as $attribute - ) { - $foundIndex = false; - foreach ( - $this->documentsIterator('indexes', [ - Query::equal('databaseInternalId', [$attribute['databaseInternalId']]), - Query::equal('collectionInternalId', [$attribute['collectionInternalId']]), - ]) as $index - ) { - if (in_array($attribute['key'], $index['attributes'])) { - $this->projectDB->deleteIndex($index['collectionId'], $index['$id']); - $foundIndex = true; + ]) as $attribute) { + $foundIndex = false; + foreach ($this->documentsIterator('indexes', [ + Query::equal('databaseInternalId', [$attribute['databaseInternalId']]), + Query::equal('collectionInternalId', [$attribute['collectionInternalId']]), + ]) as $index) { + if (in_array($attribute['key'], $index['attributes'])) { + $this->projectDB->deleteIndex($index['collectionId'], $index['$id']); + $foundIndex = true; + } + } + if ($foundIndex === true) { + $this->projectDB->updateAttribute($attribute['collectionInternalId'], $attribute['key'], $attribute['type']); } - } - if ($foundIndex === true) { - $this->projectDB->updateAttribute($attribute['collectionInternalId'], $attribute['key'], $attribute['type']); } } @@ -323,7 +323,6 @@ class V20 extends Migration */ protected function createInfMetric(string $metric, int $value): void { - try { /** * Creating inf metric @@ -351,7 +350,6 @@ class V20 extends Migration */ protected function migrateUsageMetrics(string $from, string $to): void { - /** * inf metric */ @@ -411,7 +409,6 @@ class V20 extends Migration */ private function migrateFunctions(): void { - $this->migrateUsageMetrics('deployment.$all.storage.size', 'deployments.storage'); $this->migrateUsageMetrics('builds.$all.compute.total', 'builds'); $this->migrateUsageMetrics('builds.$all.compute.time', 'builds.compute'); From 461795b6ff742016c128bb344be1ea32c1fc773c Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Sun, 18 Feb 2024 08:35:26 +0000 Subject: [PATCH 02/33] Update V17.php --- src/Appwrite/Utopia/Request/Filters/V17.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Appwrite/Utopia/Request/Filters/V17.php b/src/Appwrite/Utopia/Request/Filters/V17.php index 246b52deae..d7a4039d7e 100644 --- a/src/Appwrite/Utopia/Request/Filters/V17.php +++ b/src/Appwrite/Utopia/Request/Filters/V17.php @@ -59,6 +59,10 @@ class V17 extends Filter private function convertOldQueries(array $content): array { + if (!isset($content['queries'])) { + return $content; + } + $parsed = []; foreach ($content['queries'] as $query) { try { From bfe861f8464db978db76390e57c3c8217706fb00 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 20 Feb 2024 15:05:42 +0000 Subject: [PATCH 03/33] Run Linter --- src/Appwrite/Migration/Version/V20.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index abc2bdac8e..fdf2f5163f 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -78,14 +78,18 @@ class V20 extends Migration // Support database array type migration (user collections) if ($collectionType === 'projects') { - foreach ($this->documentsIterator('attributes', [ + foreach ( + $this->documentsIterator('attributes', [ Query::equal('array', [true]), - ]) as $attribute) { + ]) as $attribute + ) { $foundIndex = false; - foreach ($this->documentsIterator('indexes', [ + foreach ( + $this->documentsIterator('indexes', [ Query::equal('databaseInternalId', [$attribute['databaseInternalId']]), Query::equal('collectionInternalId', [$attribute['collectionInternalId']]), - ]) as $index) { + ]) as $index + ) { if (in_array($attribute['key'], $index['attributes'])) { $this->projectDB->deleteIndex($index['collectionId'], $index['$id']); $foundIndex = true; From a5d6af9dedf3c2e5a09300cd66e0c1927a08c165 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 20 Feb 2024 15:47:55 +0000 Subject: [PATCH 04/33] Add 'factors' migration --- src/Appwrite/Migration/Version/V20.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index fdf2f5163f..f43da066c4 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -540,6 +540,7 @@ class V20 extends Migration $duration = $this->project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $expire = DateTime::addSeconds(new \DateTime(), $duration); $document->setAttribute('expire', $expire); + $document->setAttribute('factors', ['email']); break; } return $document; From 370e814b8c5f87b51eafb9e92a4d13ca98b3d030 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 21 Feb 2024 09:31:52 +0000 Subject: [PATCH 05/33] Update Factors Session Migration --- src/Appwrite/Migration/Version/V20.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index f43da066c4..1796629db0 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -540,7 +540,14 @@ class V20 extends Migration $duration = $this->project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $expire = DateTime::addSeconds(new \DateTime(), $duration); $document->setAttribute('expire', $expire); - $document->setAttribute('factors', ['email']); + + $factors = match ($document->getAttribute('provider')) { + Auth::SESSION_PROVIDER_ANONYMOUS => ['anonymous'], + Auth::SESSION_PROVIDER_PHONE => ['phone'], + default => ['email'], + }; + + $document->setAttribute('factors', $factors); break; } return $document; From a2b9dbc2081d6890109e18484d0e0628a14e1560 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 21 Feb 2024 09:42:04 +0000 Subject: [PATCH 06/33] Update V20.php --- src/Appwrite/Migration/Version/V20.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 1796629db0..61f84c919b 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -47,6 +47,7 @@ class V20 extends Migration Console::info('Migrating Collections'); $this->migrateCollections(); + // No need to migrate stats for console if ($this->project->getInternalId() !== 'console') { Console::info('Migrating Functions'); $this->migrateFunctions(); From a851a5f244fae81b5eefa36f322fded6841410bd Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 21 Feb 2024 11:43:04 +0200 Subject: [PATCH 07/33] providerInternalId nulls --- app/controllers/api/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 55ad758637..5185d7eba5 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -514,7 +514,7 @@ App::post('/v1/users/:userId/targets') Permission::delete(Role::user($user->getId())), ], 'providerId' => $providerId ?? null, - 'providerInternalId' => $provider->getInternalId() ?? null, + 'providerInternalId' => $provider->isEmpty() ? null : $provider->getInternalId(), 'providerType' => $providerType, 'userId' => $userId, 'userInternalId' => $user->getInternalId(), From b762a9cedd142c3a255c65cd6d9c6d08c1614586 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 21 Feb 2024 11:48:16 +0200 Subject: [PATCH 08/33] Check user false --- app/controllers/api/users.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 5185d7eba5..0a9fbbc40e 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1660,7 +1660,7 @@ App::post('/v1/users/:userId/sessions') ->inject('queueForEvents') ->action(function (string $userId, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents) { $user = $dbForProject->getDocument('users', $userId); - if ($user === false || $user->isEmpty()) { + if ($user->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } @@ -1729,7 +1729,7 @@ App::post('/v1/users/:userId/tokens') ->action(function (string $userId, int $length, int $expire, Request $request, Response $response, Database $dbForProject, Event $queueForEvents) { $user = $dbForProject->getDocument('users', $userId); - if ($user === false || $user->isEmpty()) { + if ($user->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } From d020730a74eccc20b541bd2be6b9be942080e1a1 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 21 Feb 2024 10:20:55 +0000 Subject: [PATCH 09/33] Address Shimon's comments --- src/Appwrite/Migration/Version/V20.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 61f84c919b..e0055300e0 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -35,12 +35,6 @@ class V20 extends Migration ); } - $this->migrateUsageMetrics('project.$all.network.requests', 'network.requests'); - $this->migrateUsageMetrics('project.$all.network.outbound', 'network.outbound'); - $this->migrateUsageMetrics('project.$all.network.inbound', 'network.inbound'); - $this->migrateUsageMetrics('users.$all.count.total', 'users'); - $this->migrateSessionsMetric(); - Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); @@ -49,6 +43,12 @@ class V20 extends Migration // No need to migrate stats for console if ($this->project->getInternalId() !== 'console') { + $this->migrateUsageMetrics('project.$all.network.requests', 'network.requests'); + $this->migrateUsageMetrics('project.$all.network.outbound', 'network.outbound'); + $this->migrateUsageMetrics('project.$all.network.inbound', 'network.inbound'); + $this->migrateUsageMetrics('users.$all.count.total', 'users'); + $this->migrateSessionsMetric(); + Console::info('Migrating Functions'); $this->migrateFunctions(); From bdf044ed8cb81c0851e69f2206843386ae927a69 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 22 Feb 2024 10:21:25 +0000 Subject: [PATCH 10/33] Update 'email' to 'password' in factors --- src/Appwrite/Migration/Version/V20.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index e0055300e0..0ef899588e 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -545,7 +545,7 @@ class V20 extends Migration $factors = match ($document->getAttribute('provider')) { Auth::SESSION_PROVIDER_ANONYMOUS => ['anonymous'], Auth::SESSION_PROVIDER_PHONE => ['phone'], - default => ['email'], + default => ['password'], }; $document->setAttribute('factors', $factors); From 8742bfaee820561f1495383b9556b7e94bd8cebc Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 Feb 2024 23:56:49 +1300 Subject: [PATCH 11/33] Fix missing subscribe on topic update --- app/controllers/api/messaging.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1c30e07ba5..3e5c2666d2 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2133,21 +2133,26 @@ App::patch('/v1/messaging/topics/:topicId') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TOPIC) ->param('topicId', '', new UID(), 'Topic ID.') - ->param('name', '', new Text(128), 'Topic Name.', true) + ->param('name', null, new Text(128), 'Topic Name.', true) + ->param('subscribe', null, new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) ->inject('queueForEvents') ->inject('dbForProject') ->inject('response') - ->action(function (string $topicId, string $name, Event $queueForEvents, Database $dbForProject, Response $response) { + ->action(function (string $topicId, ?string $name, ?array $subscribe, Event $queueForEvents, Database $dbForProject, Response $response) { $topic = $dbForProject->getDocument('topics', $topicId); if ($topic->isEmpty()) { throw new Exception(Exception::TOPIC_NOT_FOUND); } - if (!empty($name)) { + if (!\is_null($name)) { $topic->setAttribute('name', $name); } + if (!\is_null($subscribe)) { + $topic->setAttribute('subscribe', $subscribe); + } + $topic = $dbForProject->updateDocument('topics', $topicId, $topic); $queueForEvents From d311f883077b3473ffc3e38741a453a93e47396b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 00:01:46 +1300 Subject: [PATCH 12/33] Add test --- tests/e2e/Services/Messaging/MessagingBase.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 25bf985692..fb3d225699 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -341,6 +341,17 @@ trait MessagingBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals('android-app', $response['body']['name']); + $response2 = $this->client->call(Client::METHOD_PATCH, '/messaging/topics/' . $topics['private']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'name' => 'ios-app', + 'subscribe' => [Role::user('some-user')->toString()], + ]); + $this->assertEquals(200, $response2['headers']['status-code']); + $this->assertEquals('ios-app', $response2['body']['name']); + return $response['body']['$id']; } From bc3e57d03ba56cf1e1a9ab29f490d6c177473f0a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 00:41:38 +1300 Subject: [PATCH 13/33] Update base + console --- .gitmodules | 2 +- Dockerfile | 2 +- app/console | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index bed812bea0..e259782156 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "app/console"] path = app/console url = https://github.com/appwrite/console - branch = chore-update-sdk + branch = 1.5.x diff --git a/Dockerfile b/Dockerfile index ccb8f8bac1..d7343dd71d 100755 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT RUN npm ci RUN npm run build -FROM appwrite/base:0.4.4 as final +FROM appwrite/base:0.9.0 as final LABEL maintainer="team@appwrite.io" diff --git a/app/console b/app/console index 44edd461c6..c72ba12e47 160000 --- a/app/console +++ b/app/console @@ -1 +1 @@ -Subproject commit 44edd461c6036cb462047c1424b80f0903cdc15e +Subproject commit c72ba12e479b0d3d9b3f4e48e01625c12a38fd7f From 40b0b637cfbf83c1048cdc3904da99eef0d21476 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 01:06:53 +1300 Subject: [PATCH 14/33] Remove opcache test --- composer.json | 2 +- composer.lock | 30 +++++++++++++-------------- tests/unit/General/ExtensionsTest.php | 5 ----- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index a53d47a3fa..171d4d6889 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ "utopia-php/cache": "0.9.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.48.2", + "utopia-php/database": "0.48.*", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index bca3e557bc..b7bb031c3c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "37887fb414be6480280484aa41c0df9d", + "content-hash": "f19c09e7e233fe0f767bf5255fb46b86", "packages": [ { "name": "adhocore/jwt", @@ -1552,16 +1552,16 @@ }, { "name": "utopia-php/database", - "version": "0.48.2", + "version": "0.48.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "0a231a2874fdbc0cf2ae2170b3f132fdee0ddfd4" + "reference": "02f20bd901b8fab26d7dc2c58f7da1d6a08d21c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/0a231a2874fdbc0cf2ae2170b3f132fdee0ddfd4", - "reference": "0a231a2874fdbc0cf2ae2170b3f132fdee0ddfd4", + "url": "https://api.github.com/repos/utopia-php/database/zipball/02f20bd901b8fab26d7dc2c58f7da1d6a08d21c0", + "reference": "02f20bd901b8fab26d7dc2c58f7da1d6a08d21c0", "shasum": "" }, "require": { @@ -1569,7 +1569,7 @@ "ext-pdo": "*", "php": ">=8.0", "utopia-php/cache": "0.9.*", - "utopia-php/framework": "0.*.*", + "utopia-php/framework": "0.33.*", "utopia-php/mongo": "0.3.*" }, "require-dev": { @@ -1602,9 +1602,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.48.2" + "source": "https://github.com/utopia-php/database/tree/0.48.4" }, - "time": "2024-02-02T14:10:14+00:00" + "time": "2024-02-23T03:22:55+00:00" }, { "name": "utopia-php/domains", @@ -3357,21 +3357,21 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353", - "reference": "bc3dc91a5e9b14aa06d1d9e90647c5c5a2cc5353", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", + "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", "phpstan/phpdoc-parser": "^1.13" }, @@ -3409,9 +3409,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2024-01-18T19:15:27+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpspec/prophecy", diff --git a/tests/unit/General/ExtensionsTest.php b/tests/unit/General/ExtensionsTest.php index d638cfffa6..f415816e56 100644 --- a/tests/unit/General/ExtensionsTest.php +++ b/tests/unit/General/ExtensionsTest.php @@ -21,11 +21,6 @@ class ExtensionsTest extends TestCase $this->assertEquals(true, extension_loaded('yaml')); } - public function testOPCache(): void - { - $this->assertEquals(true, extension_loaded('Zend OPcache')); - } - public function testDOM(): void { $this->assertEquals(true, extension_loaded('dom')); From 957f08a3ef5f43392134762045e50b5a4476f53f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 01:55:00 +1300 Subject: [PATCH 15/33] Fix max int test --- tests/e2e/Services/Databases/DatabasesBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 7f23705a1a..a0823f054f 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2973,7 +2973,7 @@ trait DatabasesBase $this->assertEquals('Invalid document structure: Attribute "floatRange" has invalid format. Value must be a valid range between 1 and 1', $badFloatRange['body']['message']); $this->assertEquals('Invalid document structure: Attribute "probability" has invalid format. Value must be a valid range between 0 and 1', $badProbability['body']['message']); $this->assertEquals('Invalid document structure: Attribute "upperBound" has invalid format. Value must be a valid range between -9,223,372,036,854,775,808 and 10', $tooHigh['body']['message']); - $this->assertEquals('Invalid document structure: Attribute "lowerBound" has invalid format. Value must be a valid range between 5 and 9,223,372,036,854,775,808', $tooLow['body']['message']); + $this->assertEquals('Invalid document structure: Attribute "lowerBound" has invalid format. Value must be a valid range between 5 and 9,223,372,036,854,775,807', $tooLow['body']['message']); } /** From 7ab80b9288cbd905b46c30f173f3849e712968b8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 02:00:31 +1300 Subject: [PATCH 16/33] Fix account method --- app/controllers/api/account.php | 2 +- tests/e2e/Services/Account/AccountCustomClientTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 22d2776daf..3f29bc1313 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3696,7 +3696,7 @@ App::post('/v1/account/mfa/challenge') ->label('audits.userId', '{response.userId}') ->label('sdk.auth', []) ->label('sdk.namespace', 'account') - ->label('sdk.method', 'create2FAChallenge') + ->label('sdk.method', 'createChallenge') ->label('sdk.description', '/docs/references/account/create-2fa-challenge.md') ->label('sdk.response.code', Response::STATUS_CODE_CREATED) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index ba525f556e..d3fc13bd17 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -2226,7 +2226,7 @@ class AccountCustomClientTest extends Scope /** * @depends testUpdatePhone */ - #[Retry(count: 2)] + #[Retry(count: 3)] public function testPhoneVerification(array $data): array { $session = $data['session'] ?? ''; From 9ae2948d0ec2c7598d47f0adfe8102514dbbc1b7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Feb 2024 13:03:56 +0100 Subject: [PATCH 17/33] fix: mfa email template --- .../locale/templates/email-mfa-challenge.tpl | 16 ++++ app/config/locale/translations/en.json | 14 ++- app/controllers/api/account.php | 86 ++++++++++++++++++- src/Appwrite/Platform/Workers/Mails.php | 8 ++ 4 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 app/config/locale/templates/email-mfa-challenge.tpl diff --git a/app/config/locale/templates/email-mfa-challenge.tpl b/app/config/locale/templates/email-mfa-challenge.tpl new file mode 100644 index 0000000000..3fc4005cb2 --- /dev/null +++ b/app/config/locale/templates/email-mfa-challenge.tpl @@ -0,0 +1,16 @@ +

{{hello}}

+ +

{{description}}

+ + + + + +
+

{{otp}}

+
+ +

{{clientInfo}}

+ +

{{thanks}}

+

{{signature}}

diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index dfa5ebe32a..438cdbde58 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -4,13 +4,13 @@ "settings.direction": "ltr", "emails.sender": "%s Team", "emails.verification.subject": "Account Verification", - "emails.verification.hello": "Hey {{user}}", + "emails.verification.hello": "Hello {{user}}", "emails.verification.body": "Follow this link to verify your email address.", "emails.verification.footer": "If you didn’t ask to verify this address, you can ignore this message.", "emails.verification.thanks": "Thanks", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "{{project}} Login", - "emails.magicSession.hello": "Hello,", + "emails.magicSession.hello": "Hello {{user}}", "emails.magicSession.optionButton": "Click the button below to securely sign in to your {{project}} account. This link will expire in 1 hour.", "emails.magicSession.buttonText": "Sign in to {{project}}", "emails.magicSession.optionUrl": "If you are unable to sign in using the button above, please visit the following link:", @@ -19,12 +19,18 @@ "emails.magicSession.thanks": "Thanks,", "emails.magicSession.signature": "{{project}} team", "emails.otpSession.subject": "OTP for {{project}} Login", - "emails.otpSession.hello": "Hello,", + "emails.otpSession.hello": "Hello {{user}}", "emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{project}} account. This code will expire in 15 minutes.", "emails.otpSession.clientInfo": "This sign in was requested using {{agentClient}} on {{agentDevice}} {{agentOs}}. If you didn't request the sign in, you can safely ignore this email.", "emails.otpSession.securityPhrase": "Security phrase for this email is {{phrase}}. You can trust this email if this phrase matches the phrase shown during sign in.", "emails.otpSession.thanks": "Thanks,", "emails.otpSession.signature": "{{project}} team", + "emails.mfaChallenge.subject": "Verification Code for {{project}}", + "emails.mfaChallenge.hello": "Hello {{user}}", + "emails.mfaChallenge.description": "Enter the following verification code to verify your email and activate two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.", + "emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.", + "emails.mfaChallenge.thanks": "Thanks,", + "emails.mfaChallenge.signature": "{{project}} team", "emails.recovery.subject": "Password Reset", "emails.recovery.hello": "Hello {{user}}", "emails.recovery.body": "Follow this link to reset your {{project}} password.", @@ -32,7 +38,7 @@ "emails.recovery.thanks": "Thanks", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitation to %s Team at %s", - "emails.invitation.hello": "Hello", + "emails.invitation.hello": "Hello {{user}}", "emails.invitation.body": "This mail was sent to you because {{owner}} wanted to invite you to become a member of the {{team}} team at {{project}}.", "emails.invitation.footer": "If you are not interested, you can ignore this message.", "emails.invitation.thanks": "Thanks", diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 3f29bc1313..d054af7f22 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3707,11 +3707,13 @@ App::post('/v1/account/mfa/challenge') ->inject('response') ->inject('dbForProject') ->inject('user') + ->inject('locale') + ->inject('project') + ->inject('request') ->inject('queueForEvents') ->inject('queueForMessaging') ->inject('queueForMails') - ->inject('locale') - ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, Locale $locale) { + ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails) { $expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM); $code = Auth::codeGenerator(); @@ -3764,9 +3766,85 @@ App::post('/v1/account/mfa/challenge') throw new Exception(Exception::USER_EMAIL_NOT_VERIFIED); } + $subject = $locale->getText("emails.mfaChallenge.subject"); + $customTemplate = $project->getAttribute('templates', [])['email.mfaChallenge-' . $locale->default] ?? []; + + $detector = new Detector($request->getUserAgent('UNKNOWN')); + $agentOs = $detector->getOS(); + $agentClient = $detector->getClient(); + $agentDevice = $detector->getDevice(); + + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-mfa-challenge.tpl'); + $message + ->setParam('{{hello}}', $locale->getText("emails.mfaChallenge.hello")) + ->setParam('{{description}}', $locale->getText("emails.mfaChallenge.description")) + ->setParam('{{clientInfo}}', $locale->getText("emails.mfaChallenge.clientInfo")) + ->setParam('{{thanks}}', $locale->getText("emails.mfaChallenge.thanks")) + ->setParam('{{signature}}', $locale->getText("emails.mfaChallenge.signature")); + + $body = $message->render(); + + $smtp = $project->getAttribute('smtp', []); + $smtpEnabled = $smtp['enabled'] ?? false; + + $senderEmail = App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); + $senderName = App::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'); + $replyTo = ""; + + if ($smtpEnabled) { + if (!empty($smtp['senderEmail'])) { + $senderEmail = $smtp['senderEmail']; + } + if (!empty($smtp['senderName'])) { + $senderName = $smtp['senderName']; + } + if (!empty($smtp['replyTo'])) { + $replyTo = $smtp['replyTo']; + } + + $queueForMails + ->setSmtpHost($smtp['host'] ?? '') + ->setSmtpPort($smtp['port'] ?? '') + ->setSmtpUsername($smtp['username'] ?? '') + ->setSmtpPassword($smtp['password'] ?? '') + ->setSmtpSecure($smtp['secure'] ?? ''); + + if (!empty($customTemplate)) { + if (!empty($customTemplate['senderEmail'])) { + $senderEmail = $customTemplate['senderEmail']; + } + if (!empty($customTemplate['senderName'])) { + $senderName = $customTemplate['senderName']; + } + if (!empty($customTemplate['replyTo'])) { + $replyTo = $customTemplate['replyTo']; + } + + $body = $customTemplate['message'] ?? ''; + $subject = $customTemplate['subject'] ?? $subject; + } + + $queueForMails + ->setSmtpReplyTo($replyTo) + ->setSmtpSenderEmail($senderEmail) + ->setSmtpSenderName($senderName); + } + + $emailVariables = [ + 'direction' => $locale->getText('settings.direction'), + /* {{user}}, {{project}} and {{otp}} are required in the templates */ + 'user' => $user->getAttribute('name'), + 'project' => $project->getAttribute('name'), + 'otp' => $code, + 'agentDevice' => $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN', + 'agentClient' => $agentClient['clientName'] ?? 'UNKNOWN', + 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN' + ]; + $queueForMails - ->setSubject("{$code} is your 6-digit code") - ->setBody($code) + ->setSubject($subject) + ->setBody($body) + ->setVariables($emailVariables) ->setRecipient($user->getAttribute('email')) ->trigger(); break; diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index ac9c44c3b9..b331f83d06 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -32,6 +32,11 @@ class Mails extends Action ->callback(fn (Message $message, Registry $register, Log $log) => $this->action($message, $register, $log)); } + protected array $richTextParams = [ + 'b' => '', + '/b' => '', + ]; + /** * @param Message $message * @param Registry $register @@ -81,6 +86,9 @@ class Mails extends Action // TODO: hotfix for redirect param $bodyTemplate->setParam('{{' . $key . '}}', $value, escapeHtml: $key !== 'redirect'); } + foreach ($this->richTextParams as $key => $value) { + $bodyTemplate->setParam('{{' . $key . '}}', $value, escapeHtml: false); + } $body = $bodyTemplate->render(); $subjectTemplate = Template::fromString($subject); From f577811c044e1a0486648100ac23951f2d9fd581 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Feb 2024 13:47:01 +0100 Subject: [PATCH 18/33] fix: formatting on emails --- .../locale/templates/email-inner-base.tpl | 2 +- app/config/locale/translations/en.json | 18 +++---- app/controllers/api/account.php | 51 ++++++++++++------- phpunit.xml | 2 +- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/app/config/locale/templates/email-inner-base.tpl b/app/config/locale/templates/email-inner-base.tpl index 52e1093ffb..aa3457412d 100644 --- a/app/config/locale/templates/email-inner-base.tpl +++ b/app/config/locale/templates/email-inner-base.tpl @@ -1,4 +1,4 @@ -

{{hello}},

+

{{hello}}

{{body}}

{{redirect}}

{{footer}}

diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index 438cdbde58..22a132964e 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -5,24 +5,24 @@ "emails.sender": "%s Team", "emails.verification.subject": "Account Verification", "emails.verification.hello": "Hello {{user}}", - "emails.verification.body": "Follow this link to verify your email address.", + "emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.", "emails.verification.footer": "If you didn’t ask to verify this address, you can ignore this message.", "emails.verification.thanks": "Thanks", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "{{project}} Login", "emails.magicSession.hello": "Hello {{user}}", - "emails.magicSession.optionButton": "Click the button below to securely sign in to your {{project}} account. This link will expire in 1 hour.", + "emails.magicSession.optionButton": "Click the button below to securely sign in to your {{b}}{{project}}{{/b}} account. This link will expire in 1 hour.", "emails.magicSession.buttonText": "Sign in to {{project}}", "emails.magicSession.optionUrl": "If you are unable to sign in using the button above, please visit the following link:", - "emails.magicSession.clientInfo": "This sign in was requested using {{agentClient}} on {{agentDevice}} {{agentOs}}. If you didn't request the sign in, you can safely ignore this email.", - "emails.magicSession.securityPhrase": "Security phrase for this email is {{phrase}}. You can trust this email if this phrase matches the phrase shown during sign in.", + "emails.magicSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.", + "emails.magicSession.securityPhrase": "Security phrase for this email is {{b}}{{phrase}}{{/b}}. You can trust this email if this phrase matches the phrase shown during sign in.", "emails.magicSession.thanks": "Thanks,", "emails.magicSession.signature": "{{project}} team", "emails.otpSession.subject": "OTP for {{project}} Login", "emails.otpSession.hello": "Hello {{user}}", - "emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{project}} account. This code will expire in 15 minutes.", - "emails.otpSession.clientInfo": "This sign in was requested using {{agentClient}} on {{agentDevice}} {{agentOs}}. If you didn't request the sign in, you can safely ignore this email.", - "emails.otpSession.securityPhrase": "Security phrase for this email is {{phrase}}. You can trust this email if this phrase matches the phrase shown during sign in.", + "emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.", + "emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.", + "emails.otpSession.securityPhrase": "Security phrase for this email is {{b}}{{phrase}}{{/b}}. You can trust this email if this phrase matches the phrase shown during sign in.", "emails.otpSession.thanks": "Thanks,", "emails.otpSession.signature": "{{project}} team", "emails.mfaChallenge.subject": "Verification Code for {{project}}", @@ -33,13 +33,13 @@ "emails.mfaChallenge.signature": "{{project}} team", "emails.recovery.subject": "Password Reset", "emails.recovery.hello": "Hello {{user}}", - "emails.recovery.body": "Follow this link to reset your {{project}} password.", + "emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.", "emails.recovery.footer": "If you didn’t ask to reset your password, you can ignore this message.", "emails.recovery.thanks": "Thanks", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitation to %s Team at %s", "emails.invitation.hello": "Hello {{user}}", - "emails.invitation.body": "This mail was sent to you because {{owner}} wanted to invite you to become a member of the {{team}} team at {{project}}.", + "emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} wanted to invite you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.", "emails.invitation.footer": "If you are not interested, you can ignore this message.", "emails.invitation.thanks": "Thanks", "emails.invitation.signature": "{{project}} team", diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index d054af7f22..a68a882e43 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1259,15 +1259,14 @@ App::post('/v1/account/tokens/magic-url') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ - 'user' => '', - 'team' => '', + /* {{user}}, {{redirect}} and {{project}} are required in default and custom templates */ + 'user' => $user->getAttribute('name'), 'project' => $project->getAttribute('name'), 'redirect' => $url, - 'agentDevice' => '' . ( $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN') . '', - 'agentClient' => '' . ($agentClient['clientName'] ?? 'UNKNOWN') . '', - 'agentOs' => '' . ($agentOs['osName'] ?? 'UNKNOWN') . '', - 'phrase' => '' . (!empty($phrase) ? $phrase : '') . '' + 'agentDevice' => $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN', + 'agentClient' => $agentClient['clientName'] ?? 'UNKNOWN', + 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN', + 'phrase' => !empty($phrase) ? $phrase : '' ]; $queueForMails @@ -1487,15 +1486,14 @@ App::post('/v1/account/tokens/email') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}} ,{{team}}, {{project}} and {{otp}} are required in the templates */ - 'user' => '', - 'team' => '', + /* {{user}}, {{project}} and {{otp}} are required in the templates */ + 'user' => $user->getAttribute('name'), 'project' => $project->getAttribute('name'), 'otp' => $tokenSecret, - 'agentDevice' => '' . ( $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN') . '', - 'agentClient' => '' . ($agentClient['clientName'] ?? 'UNKNOWN') . '', - 'agentOs' => '' . ($agentOs['osName'] ?? 'UNKNOWN') . '', - 'phrase' => '' . (!empty($phrase) ? $phrase : '') . '' + 'agentDevice' => $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN', + 'agentClient' => $agentClient['clientName'] ?? 'UNKNOWN', + 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN', + 'phrase' => !empty($phrase) ? $phrase : '' ]; $queueForMails @@ -2953,9 +2951,8 @@ App::post('/v1/account/recovery') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ + /* {{user}}, {{redirect}} and {{project}} are required in default and custom templates */ 'user' => $profile->getAttribute('name'), - 'team' => '', 'redirect' => $url, 'project' => $projectName ]; @@ -3200,9 +3197,8 @@ App::post('/v1/account/verification') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ + /* {{user}}, {{redirect}} and {{project}} are required in default and custom templates */ 'user' => $user->getAttribute('name'), - 'team' => '', 'redirect' => $url, 'project' => $projectName ]; @@ -3745,6 +3741,22 @@ App::post('/v1/account/mfa/challenge') throw new Exception(Exception::USER_PHONE_NOT_VERIFIED); } + $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); + + $customTemplate = $project->getAttribute('templates', [])['sms.mfa-challenge-' . $locale->default] ?? []; + if (!empty($customTemplate)) { + $message = $customTemplate['message'] ?? $message; + } + + $messageContent = Template::fromString($locale->getText("sms.verification.body")); + $messageContent + ->setParam('{{project}}', $project->getAttribute('name')) + ->setParam('{{secret}}', $code); + $messageContent = \strip_tags($messageContent->render()); + $message = $message->setParam('{{token}}', $messageContent); + + $message = $message->render(); + $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage(new Document([ @@ -3753,7 +3765,8 @@ App::post('/v1/account/mfa/challenge') 'content' => $code, ], ])) - ->setRecipients([$user->getAttribute('phone')]); + ->setRecipients([$user->getAttribute('phone')]) + ->setProviderType(MESSAGE_TYPE_SMS); break; case 'email': if (empty(App::getEnv('_APP_SMTP_HOST'))) { diff --git a/phpunit.xml b/phpunit.xml index 90ebd4225f..e772866051 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" > From c1ae63777e34e5cd533157246eb1f18f9a07ab80 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Feb 2024 13:50:38 +0100 Subject: [PATCH 19/33] revert: phpunit.xml change --- phpunit.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml b/phpunit.xml index e772866051..90ebd4225f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" > From f5cdd5e4cc16876d0223ad15916505a21bbd10da Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Feb 2024 14:34:46 +0100 Subject: [PATCH 20/33] fix: comma in email templates --- app/config/locale/translations/en.json | 12 ++++++------ src/Appwrite/Platform/Workers/Mails.php | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index 22a132964e..12c296d78f 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -4,13 +4,13 @@ "settings.direction": "ltr", "emails.sender": "%s Team", "emails.verification.subject": "Account Verification", - "emails.verification.hello": "Hello {{user}}", + "emails.verification.hello": "Hello {{user}},", "emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.", "emails.verification.footer": "If you didn’t ask to verify this address, you can ignore this message.", "emails.verification.thanks": "Thanks", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "{{project}} Login", - "emails.magicSession.hello": "Hello {{user}}", + "emails.magicSession.hello": "Hello {{user}},", "emails.magicSession.optionButton": "Click the button below to securely sign in to your {{b}}{{project}}{{/b}} account. This link will expire in 1 hour.", "emails.magicSession.buttonText": "Sign in to {{project}}", "emails.magicSession.optionUrl": "If you are unable to sign in using the button above, please visit the following link:", @@ -19,26 +19,26 @@ "emails.magicSession.thanks": "Thanks,", "emails.magicSession.signature": "{{project}} team", "emails.otpSession.subject": "OTP for {{project}} Login", - "emails.otpSession.hello": "Hello {{user}}", + "emails.otpSession.hello": "Hello {{user}},", "emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.", "emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.", "emails.otpSession.securityPhrase": "Security phrase for this email is {{b}}{{phrase}}{{/b}}. You can trust this email if this phrase matches the phrase shown during sign in.", "emails.otpSession.thanks": "Thanks,", "emails.otpSession.signature": "{{project}} team", "emails.mfaChallenge.subject": "Verification Code for {{project}}", - "emails.mfaChallenge.hello": "Hello {{user}}", + "emails.mfaChallenge.hello": "Hello {{user}},", "emails.mfaChallenge.description": "Enter the following verification code to verify your email and activate two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.", "emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.", "emails.mfaChallenge.thanks": "Thanks,", "emails.mfaChallenge.signature": "{{project}} team", "emails.recovery.subject": "Password Reset", - "emails.recovery.hello": "Hello {{user}}", + "emails.recovery.hello": "Hello {{user}},", "emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.", "emails.recovery.footer": "If you didn’t ask to reset your password, you can ignore this message.", "emails.recovery.thanks": "Thanks", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitation to %s Team at %s", - "emails.invitation.hello": "Hello {{user}}", + "emails.invitation.hello": "Hello {{user}},", "emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} wanted to invite you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.", "emails.invitation.footer": "If you are not interested, you can ignore this message.", "emails.invitation.thanks": "Thanks", diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index b331f83d06..57d1baa978 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -32,6 +32,9 @@ class Mails extends Action ->callback(fn (Message $message, Registry $register, Log $log) => $this->action($message, $register, $log)); } + /** + * @var array + */ protected array $richTextParams = [ 'b' => '', '/b' => '', From af6091e04aafcfd5f7d74b1f2fe884c12d51a1cd Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 22 Feb 2024 14:37:01 +0100 Subject: [PATCH 21/33] fix: template name typo for mfa challenge --- app/controllers/api/account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index a68a882e43..3dcda9d898 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3743,7 +3743,7 @@ App::post('/v1/account/mfa/challenge') $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - $customTemplate = $project->getAttribute('templates', [])['sms.mfa-challenge-' . $locale->default] ?? []; + $customTemplate = $project->getAttribute('templates', [])['sms.mfaChallenge-' . $locale->default] ?? []; if (!empty($customTemplate)) { $message = $customTemplate['message'] ?? $message; } From 6a8140a80f5009b427c6d7149c6c21205bf104d6 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 23 Feb 2024 00:52:20 +0100 Subject: [PATCH 22/33] fix: move comma from language files into templates --- app/config/locale/templates/email-inner-base.tpl | 2 +- app/config/locale/templates/email-magic-url.tpl | 2 +- app/config/locale/templates/email-mfa-challenge.tpl | 2 +- app/config/locale/templates/email-otp.tpl | 2 +- app/config/locale/translations/en.json | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/config/locale/templates/email-inner-base.tpl b/app/config/locale/templates/email-inner-base.tpl index aa3457412d..52e1093ffb 100644 --- a/app/config/locale/templates/email-inner-base.tpl +++ b/app/config/locale/templates/email-inner-base.tpl @@ -1,4 +1,4 @@ -

{{hello}}

+

{{hello}},

{{body}}

{{redirect}}

{{footer}}

diff --git a/app/config/locale/templates/email-magic-url.tpl b/app/config/locale/templates/email-magic-url.tpl index 21988c5bc1..def1ea2395 100644 --- a/app/config/locale/templates/email-magic-url.tpl +++ b/app/config/locale/templates/email-magic-url.tpl @@ -1,4 +1,4 @@ -

{{hello}}

+

{{hello}},

{{optionButton}}

diff --git a/app/config/locale/templates/email-mfa-challenge.tpl b/app/config/locale/templates/email-mfa-challenge.tpl index 3fc4005cb2..cf09448ca5 100644 --- a/app/config/locale/templates/email-mfa-challenge.tpl +++ b/app/config/locale/templates/email-mfa-challenge.tpl @@ -1,4 +1,4 @@ -

{{hello}}

+

{{hello}},

{{description}}

diff --git a/app/config/locale/templates/email-otp.tpl b/app/config/locale/templates/email-otp.tpl index 84802c1603..9552185f84 100644 --- a/app/config/locale/templates/email-otp.tpl +++ b/app/config/locale/templates/email-otp.tpl @@ -1,4 +1,4 @@ -

{{hello}}

+

{{hello}},

{{description}}

diff --git a/app/config/locale/translations/en.json b/app/config/locale/translations/en.json index 12c296d78f..22a132964e 100644 --- a/app/config/locale/translations/en.json +++ b/app/config/locale/translations/en.json @@ -4,13 +4,13 @@ "settings.direction": "ltr", "emails.sender": "%s Team", "emails.verification.subject": "Account Verification", - "emails.verification.hello": "Hello {{user}},", + "emails.verification.hello": "Hello {{user}}", "emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.", "emails.verification.footer": "If you didn’t ask to verify this address, you can ignore this message.", "emails.verification.thanks": "Thanks", "emails.verification.signature": "{{project}} team", "emails.magicSession.subject": "{{project}} Login", - "emails.magicSession.hello": "Hello {{user}},", + "emails.magicSession.hello": "Hello {{user}}", "emails.magicSession.optionButton": "Click the button below to securely sign in to your {{b}}{{project}}{{/b}} account. This link will expire in 1 hour.", "emails.magicSession.buttonText": "Sign in to {{project}}", "emails.magicSession.optionUrl": "If you are unable to sign in using the button above, please visit the following link:", @@ -19,26 +19,26 @@ "emails.magicSession.thanks": "Thanks,", "emails.magicSession.signature": "{{project}} team", "emails.otpSession.subject": "OTP for {{project}} Login", - "emails.otpSession.hello": "Hello {{user}},", + "emails.otpSession.hello": "Hello {{user}}", "emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.", "emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.", "emails.otpSession.securityPhrase": "Security phrase for this email is {{b}}{{phrase}}{{/b}}. You can trust this email if this phrase matches the phrase shown during sign in.", "emails.otpSession.thanks": "Thanks,", "emails.otpSession.signature": "{{project}} team", "emails.mfaChallenge.subject": "Verification Code for {{project}}", - "emails.mfaChallenge.hello": "Hello {{user}},", + "emails.mfaChallenge.hello": "Hello {{user}}", "emails.mfaChallenge.description": "Enter the following verification code to verify your email and activate two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.", "emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.", "emails.mfaChallenge.thanks": "Thanks,", "emails.mfaChallenge.signature": "{{project}} team", "emails.recovery.subject": "Password Reset", - "emails.recovery.hello": "Hello {{user}},", + "emails.recovery.hello": "Hello {{user}}", "emails.recovery.body": "Follow this link to reset your {{b}}{{project}}{{/b}} password.", "emails.recovery.footer": "If you didn’t ask to reset your password, you can ignore this message.", "emails.recovery.thanks": "Thanks", "emails.recovery.signature": "{{project}} team", "emails.invitation.subject": "Invitation to %s Team at %s", - "emails.invitation.hello": "Hello {{user}},", + "emails.invitation.hello": "Hello {{user}}", "emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} wanted to invite you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.", "emails.invitation.footer": "If you are not interested, you can ignore this message.", "emails.invitation.thanks": "Thanks", From 076ffe8866d50c64e8c7c1e35c4525958541c7e3 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 23 Feb 2024 01:46:13 +0100 Subject: [PATCH 23/33] fix: missing team variable and added mfa templates to config --- app/config/locale/templates.php | 4 +++- app/controllers/api/account.php | 26 +++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/config/locale/templates.php b/app/config/locale/templates.php index f2672c04a0..ac5a2acf1d 100644 --- a/app/config/locale/templates.php +++ b/app/config/locale/templates.php @@ -6,10 +6,12 @@ return [ 'magicSession', 'recovery', 'invitation', + 'mfaChallenge' ], 'sms' => [ 'verification', 'login', - 'invitation' + 'invitation', + 'mfaChallenge' ] ]; diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 3dcda9d898..4d3a592bc5 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1259,14 +1259,16 @@ App::post('/v1/account/tokens/magic-url') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{redirect}} and {{project}} are required in default and custom templates */ + // {{user}}, {{redirect}} and {{project}} are required in default and custom templates 'user' => $user->getAttribute('name'), 'project' => $project->getAttribute('name'), 'redirect' => $url, 'agentDevice' => $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN', 'agentClient' => $agentClient['clientName'] ?? 'UNKNOWN', 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN', - 'phrase' => !empty($phrase) ? $phrase : '' + 'phrase' => !empty($phrase) ? $phrase : '', + // TODO: remove unnecessary team variable from this email + 'team' => '', ]; $queueForMails @@ -1486,14 +1488,16 @@ App::post('/v1/account/tokens/email') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{project}} and {{otp}} are required in the templates */ + // {{user}}, {{project}} and {{otp}} are required in the templates 'user' => $user->getAttribute('name'), 'project' => $project->getAttribute('name'), 'otp' => $tokenSecret, 'agentDevice' => $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN', 'agentClient' => $agentClient['clientName'] ?? 'UNKNOWN', 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN', - 'phrase' => !empty($phrase) ? $phrase : '' + 'phrase' => !empty($phrase) ? $phrase : '', + // TODO: remove unnecessary team variable from this email + 'team' => '', ]; $queueForMails @@ -2951,10 +2955,12 @@ App::post('/v1/account/recovery') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{redirect}} and {{project}} are required in default and custom templates */ + // {{user}}, {{redirect}} and {{project}} are required in default and custom templates 'user' => $profile->getAttribute('name'), 'redirect' => $url, - 'project' => $projectName + 'project' => $projectName, + // TODO: remove unnecessary team variable from this email + 'team' => '' ]; $queueForMails @@ -3197,10 +3203,12 @@ App::post('/v1/account/verification') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{redirect}} and {{project}} are required in default and custom templates */ + // {{user}}, {{redirect}} and {{project}} are required in default and custom templates 'user' => $user->getAttribute('name'), 'redirect' => $url, - 'project' => $projectName + 'project' => $projectName, + // TODO: remove unnecessary team variable from this email + 'team' => '', ]; $queueForMails @@ -3845,7 +3853,7 @@ App::post('/v1/account/mfa/challenge') $emailVariables = [ 'direction' => $locale->getText('settings.direction'), - /* {{user}}, {{project}} and {{otp}} are required in the templates */ + // {{user}}, {{project}} and {{otp}} are required in the templates 'user' => $user->getAttribute('name'), 'project' => $project->getAttribute('name'), 'otp' => $code, From 11e9f4398203a3de424f356dbc46d32ecab693c6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 13:34:08 +1300 Subject: [PATCH 24/33] Allow setting APNS to sandbox mode --- app/controllers/api/messaging.php | 19 +++++++++++++++++-- src/Appwrite/Platform/Workers/Messaging.php | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1c30e07ba5..4a75e03b47 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -766,11 +766,12 @@ App::post('/v1/messaging/providers/apns') ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) ->param('teamId', '', new Text(0), 'APNS team ID.', true) ->param('bundleId', '', new Text(0), 'APNS bundle ID.', true) + ->param('sandbox', false, new Boolean(), 'Use APNS sandbox environment.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) ->inject('queueForEvents') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, string $authKey, string $authKeyId, string $teamId, string $bundleId, bool $sandbox, ?bool $enabled, Event $queueForEvents, Database $dbForProject, Response $response) { $providerId = $providerId == 'unique()' ? ID::unique() : $providerId; $credentials = []; @@ -803,6 +804,10 @@ App::post('/v1/messaging/providers/apns') $enabled = false; } + $options = [ + 'sandbox' => $sandbox + ]; + $provider = new Document([ '$id' => $providerId, 'name' => $name, @@ -810,6 +815,7 @@ App::post('/v1/messaging/providers/apns') 'type' => MESSAGE_TYPE_PUSH, 'enabled' => $enabled, 'credentials' => $credentials, + 'options' => $options ]); try { @@ -1808,10 +1814,11 @@ App::patch('/v1/messaging/providers/apns/:providerId') ->param('authKeyId', '', new Text(0), 'APNS authentication key ID.', true) ->param('teamId', '', new Text(0), 'APNS team ID.', true) ->param('bundleId', '', new Text(0), 'APNS bundle ID.', true) + ->param('sandbox', null, new Boolean(), 'Use APNS sandbox environment.', true) ->inject('queueForEvents') ->inject('dbForProject') ->inject('response') - ->action(function (string $providerId, string $name, ?bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, Event $queueForEvents, Database $dbForProject, Response $response) { + ->action(function (string $providerId, string $name, ?bool $enabled, string $authKey, string $authKeyId, string $teamId, string $bundleId, ?bool $sandbox, Event $queueForEvents, Database $dbForProject, Response $response) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1847,6 +1854,14 @@ App::patch('/v1/messaging/providers/apns/:providerId') $provider->setAttribute('credentials', $credentials); + $options = $provider->getAttribute('options'); + + if (!\is_null($sandbox)) { + $options['sandbox'] = $sandbox; + } + + $provider->setAttribute('options', $options); + if (!\is_null($enabled)) { if ($enabled) { if ( diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 62e58db11a..aacd49f94a 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -469,6 +469,7 @@ class Messaging extends Action private function getPushAdapter(Document $provider): ?PushAdapter { $credentials = $provider->getAttribute('credentials'); + $options = $provider->getAttribute('options'); return match ($provider->getAttribute('provider')) { 'mock' => new Mock('username', 'password'), @@ -477,6 +478,7 @@ class Messaging extends Action $credentials['authKeyId'], $credentials['teamId'], $credentials['bundleId'], + $options['sandbox'] ), 'fcm' => new FCM(\json_encode($credentials['serviceAccountJSON'])), default => null From 0ccdce8feb08f56f184448e4a62d5dbaa6e7ebc3 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 13:46:45 +1300 Subject: [PATCH 25/33] Add test --- tests/e2e/Services/Messaging/MessagingBase.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 25bf985692..1ec4bfd416 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -98,16 +98,22 @@ trait MessagingBase ]; $providers = []; - foreach (\array_keys($providersParams) as $key) { + foreach ($providersParams as $key => $params) { $response = $this->client->call(Client::METHOD_POST, '/messaging/providers/' . $key, \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], - ]), $providersParams[$key]); + ]), $params); $this->assertEquals(201, $response['headers']['status-code']); - $this->assertEquals($providersParams[$key]['name'], $response['body']['name']); - \array_push($providers, $response['body']); + $this->assertEquals($params['name'], $response['body']['name']); + $providers[] = $response['body']; + + switch ($key) { + case 'apns': + $this->assertEquals(false, $response['body']['options']['sandbox']); + break; + } } return $providers; From bae1ba714c8625384351612cb081499b12f927f6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 14:16:05 +1300 Subject: [PATCH 26/33] Enum format fixes --- src/Appwrite/Specification/Format.php | 7 ++++--- tests/e2e/Services/GraphQL/Base.php | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Specification/Format.php b/src/Appwrite/Specification/Format.php index c58d69fcb9..70a86e4f5a 100644 --- a/src/Appwrite/Specification/Format.php +++ b/src/Appwrite/Specification/Format.php @@ -116,6 +116,7 @@ abstract class Format case 'account': switch ($method) { case 'createOAuth2Session': + case 'createOAuth2Token': switch ($param) { case 'provider': return 'OAuthProvider'; @@ -219,11 +220,11 @@ abstract class Format return 'MessageStatus'; } break; - case 'createSMTPProvider': - case 'updateSMTPProvider': + case 'createSmtpProvider': + case 'updateSmtpProvider': switch ($param) { case 'encryption': - return 'SMTPEncryption'; + return 'SmtpEncryption'; } break; } diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 01153cdd04..f8c61186ab 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1812,8 +1812,8 @@ trait Base } }'; case self::$CREATE_SMTP_PROVIDER: - return 'mutation createSMTPProvider($providerId: String!, $name: String!, $host: String!, $port: Int!, $username: String!, $password: String!, $encryption: String!, $autoTLS: Boolean! $fromName: String!, $fromEmail: String!, $replyToName: String, $replyToEmail: String) { - messagingCreateSMTPProvider(providerId: $providerId, name: $name, host: $host, port: $port, username: $username, password: $password, encryption: $encryption, autoTLS: $autoTLS, fromName: $fromName, fromEmail: $fromEmail, replyToName: $replyToName, replyToEmail: $replyToEmail) { + return 'mutation createSmtpProvider($providerId: String!, $name: String!, $host: String!, $port: Int!, $username: String!, $password: String!, $encryption: String!, $autoTLS: Boolean! $fromName: String!, $fromEmail: String!, $replyToName: String, $replyToEmail: String) { + messagingCreateSmtpProvider(providerId: $providerId, name: $name, host: $host, port: $port, username: $username, password: $password, encryption: $encryption, autoTLS: $autoTLS, fromName: $fromName, fromEmail: $fromEmail, replyToName: $replyToName, replyToEmail: $replyToEmail) { _id name provider @@ -1936,8 +1936,8 @@ trait Base } }'; case self::$UPDATE_SMTP_PROVIDER: - return 'mutation updateSMTPProvider($providerId: String!, $name: String!, $host: String!, $port: Int!, $username: String!, $password: String!, $encryption: String!, $autoTLS: Boolean!, $fromName: String, $fromEmail: String, $enabled: Boolean) { - messagingUpdateSMTPProvider(providerId: $providerId, name: $name, host: $host, port: $port, username: $username, password: $password, encryption: $encryption, autoTLS: $autoTLS, fromName: $fromName, fromEmail: $fromEmail, enabled: $enabled) { + return 'mutation updateSmtpProvider($providerId: String!, $name: String!, $host: String!, $port: Int!, $username: String!, $password: String!, $encryption: String!, $autoTLS: Boolean!, $fromName: String, $fromEmail: String, $enabled: Boolean) { + messagingUpdateSmtpProvider(providerId: $providerId, name: $name, host: $host, port: $port, username: $username, password: $password, encryption: $encryption, autoTLS: $autoTLS, fromName: $fromName, fromEmail: $fromEmail, enabled: $enabled) { _id name provider From c948d3a48500f69899b70399d7a4ea2a65762270 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 Feb 2024 15:04:40 +1300 Subject: [PATCH 27/33] Debug dump errors --- tests/e2e/Services/Functions/FunctionsCustomClientTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 8a5031f6ae..12dd7cda59 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -135,7 +135,7 @@ class FunctionsCustomClientTest extends Scope \sleep(1); } - $this->assertEquals('ready', $deployment['body']['status']); + $this->assertEquals('ready', $deployment['body']['status'], \json_encode($deployment['body'])); $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $function['body']['$id'] . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', @@ -266,7 +266,7 @@ class FunctionsCustomClientTest extends Scope \sleep(1); } - $this->assertEquals('ready', $deployment['body']['status']); + $this->assertEquals('ready', $deployment['body']['status'], \json_encode($deployment['body'])); $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', From 937393a8213991ef43f44127b21eafd87cd52696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 Feb 2024 11:44:55 +0100 Subject: [PATCH 28/33] Show details in CI/CD --- .github/workflows/tests.yml | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9c9b678302..bb50fa1bdf 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -108,22 +108,22 @@ jobs: matrix: service: [ - Account, - Avatars, - Console, - Databases, + # Account, + # Avatars, + # Console, + # Databases, Functions, - GraphQL, - Health, - Locale, - Projects, - Realtime, - Storage, - Teams, - Users, - Webhooks, - VCS, - Messaging, + # GraphQL, + # Health, + # Locale, + # Projects, + # Realtime, + # Storage, + # Teams, + # Users, + # Webhooks, + # VCS, + # Messaging, ] steps: @@ -142,6 +142,10 @@ jobs: docker load --input /tmp/${{ env.IMAGE }}.tar docker compose up -d sleep 10 + docker compose ls + docker compose ps + docker compose logs openruntimes-proxy + docker compose logs openruntimes-executor - name: Run ${{matrix.service}} Tests run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug From 23015aa80c460332b33872b957fb528fc1a714e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 Feb 2024 11:52:52 +0100 Subject: [PATCH 29/33] Increase sleep to allow warmup --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bb50fa1bdf..a66265cb6c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -141,7 +141,7 @@ jobs: run: | docker load --input /tmp/${{ env.IMAGE }}.tar docker compose up -d - sleep 10 + sleep 30 docker compose ls docker compose ps docker compose logs openruntimes-proxy From 6cfff74ea4e3ff0748694159a8a1ef237ed8f9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 Feb 2024 12:11:13 +0100 Subject: [PATCH 30/33] Decrease wait --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a66265cb6c..44ad3c1356 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -141,7 +141,7 @@ jobs: run: | docker load --input /tmp/${{ env.IMAGE }}.tar docker compose up -d - sleep 30 + sleep 20 docker compose ls docker compose ps docker compose logs openruntimes-proxy From 764e8093f2a1eecd277aef98006e2bd353aa3268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 Feb 2024 12:20:31 +0100 Subject: [PATCH 31/33] Update tests.yml --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 44ad3c1356..b85f7c8d9e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -141,7 +141,7 @@ jobs: run: | docker load --input /tmp/${{ env.IMAGE }}.tar docker compose up -d - sleep 20 + sleep 25 docker compose ls docker compose ps docker compose logs openruntimes-proxy From 43b3eca3c98bd26c581f1e4aa709df0162efd74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 Feb 2024 12:27:09 +0100 Subject: [PATCH 32/33] Remove leftovers --- .github/workflows/tests.yml | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b85f7c8d9e..2cc4c700f7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -108,22 +108,22 @@ jobs: matrix: service: [ - # Account, - # Avatars, - # Console, - # Databases, + Account, + Avatars, + Console, + Databases, Functions, - # GraphQL, - # Health, - # Locale, - # Projects, - # Realtime, - # Storage, - # Teams, - # Users, - # Webhooks, - # VCS, - # Messaging, + GraphQL, + Health, + Locale, + Projects, + Realtime, + Storage, + Teams, + Users, + Webhooks, + VCS, + Messaging, ] steps: @@ -142,10 +142,6 @@ jobs: docker load --input /tmp/${{ env.IMAGE }}.tar docker compose up -d sleep 25 - docker compose ls - docker compose ps - docker compose logs openruntimes-proxy - docker compose logs openruntimes-executor - name: Run ${{matrix.service}} Tests run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug From 7a24f5fb3dc9a6480d61b7940c51eff21ed65216 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sun, 25 Feb 2024 02:21:33 +1300 Subject: [PATCH 33/33] Fix missing userId on update challenge --- app/controllers/api/account.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 4d3a592bc5..eec259f321 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -3940,6 +3940,9 @@ App::put('/v1/account/mfa/challenge') $dbForProject->updateDocument('sessions', $sessionId, $session->setAttribute('factors', $provider, Document::SET_TYPE_APPEND)); + $queueForEvents + ->setParam('userId', $user->getId()); + $response->dynamic($session, Response::MODEL_SESSION); });