From c96f1e76e2296a7dabc5750484a809d57ec8ef5c Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 5 Aug 2022 15:50:48 +0530 Subject: [PATCH 01/75] feat: add new attributes for API Keys --- app/config/collections.php | 29 ++++++++++++++++++++++ app/controllers/api/projects.php | 2 ++ app/controllers/general.php | 1 + src/Appwrite/Utopia/Response/Model/Key.php | 12 +++++++++ 4 files changed, 44 insertions(+) diff --git a/app/config/collections.php b/app/config/collections.php index ecbe92c333..2f0949910c 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -972,6 +972,28 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'sdks', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], ], 'indexes' => [ [ @@ -981,6 +1003,13 @@ $collections = [ 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], ], ], diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 214af8e440..7eca6cfdc3 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -841,6 +841,8 @@ App::post('/v1/projects/:projectId/keys') 'name' => $name, 'scopes' => $scopes, 'expire' => $expire, + 'sdks' => [], + 'accessedAt' => 0, 'secret' => \bin2hex(\random_bytes(128)), ]); diff --git a/app/controllers/general.php b/app/controllers/general.php index c87d53c290..87edbdcff4 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -281,6 +281,7 @@ App::init() * Mock user to app and grant API key scopes in addition to default app scopes */ if ($key && $user->isEmpty()) { + var_dump($key); $user = new Document([ '$id' => '', 'status' => true, diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 5c79c28b55..263725996a 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -58,6 +58,18 @@ class Key extends Model 'default' => '', 'example' => '919c2d18fb5d4...a2ae413da83346ad2', ]) + ->addRule('accessedAt', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Most recent access date in Unix timestamp.', + 'default' => null, + 'example' => '1653990687', + ]) + ->addRule('sdks', [ + 'type' => self::TYPE_STRING, + 'description' => 'List of SDK user agents that used this key.', + 'default' => null, + 'example' => 'appwrite:flutter', + ]) ; } From 1dc9f5e842401de5b27554b929576c5a9d121478 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 5 Aug 2022 17:38:04 +0530 Subject: [PATCH 02/75] feat: add new attributes for API Keys --- app/controllers/general.php | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 87edbdcff4..265a41ee25 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -30,6 +30,7 @@ use Appwrite\Utopia\Request\Filters\V12 as RequestV12; use Appwrite\Utopia\Request\Filters\V13 as RequestV13; use Appwrite\Utopia\Request\Filters\V14 as RequestV14; use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); @@ -281,7 +282,6 @@ App::init() * Mock user to app and grant API key scopes in addition to default app scopes */ if ($key && $user->isEmpty()) { - var_dump($key); $user = new Document([ '$id' => '', 'status' => true, @@ -301,6 +301,35 @@ App::init() Authorization::setRole('role:' . Auth::USER_ROLE_APP); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. + + if (time() > ($key->getAttribute('accessedAt', 0) + (24 * 60 * 60))) { + $key->setAttribute('accessedAt', time()); + $sdkValidator = new WhiteList([ + 'appwrite:nodejs', + 'appwrite:deno', + 'appwrite:php', + 'appwrite:python', + 'appwrite:ruby', + 'appwrite:go', + 'appwrite:java', + 'appwrite:dotnet', + 'appwrite:dart', + 'appwrite:kotlin', + 'appwrite:swift' + ], true); + + $sdk = $request->getHeader('x-sdk-version', 'UNKNOWN'); + $sdk = substr($sdk, 0, strrpos($sdk, ':')); + + if ($sdkValidator->isValid($sdk)) { + $sdks = $key->getAttribute('sdks', []); + array_push($sdks, $sdk); + $key->setAttribute('sdks', $sdks); + } + + $dbForConsole->updateDocument('keys', $key->getId(), $key); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); + } } } From 82e39ccf524d77b6ef293bd61da237cf47a37a5b Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 01:12:13 +0530 Subject: [PATCH 03/75] feat: review comments --- app/controllers/general.php | 2 +- app/init.php | 1 + src/Appwrite/Utopia/Response/Model/Key.php | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 265a41ee25..5cdf0f4995 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -302,7 +302,7 @@ App::init() Authorization::setRole('role:' . Auth::USER_ROLE_APP); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - if (time() > ($key->getAttribute('accessedAt', 0) + (24 * 60 * 60))) { + if (time() > $key->getAttribute('accessedAt', 0) + APP_KEY_USAGE) { $key->setAttribute('accessedAt', time()); $sdkValidator = new WhiteList([ 'appwrite:nodejs', diff --git a/app/init.php b/app/init.php index 146a4fc2a7..d09b08a1d8 100644 --- a/app/init.php +++ b/app/init.php @@ -88,6 +88,7 @@ const APP_LIMIT_COMPRESSION = 20000000; //20MB const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length. const APP_LIMIT_SUBQUERY = 1000; +const APP_KEY_USAGE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 402; const APP_VERSION_STABLE = '0.15.3'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 263725996a..811888a87e 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -69,6 +69,7 @@ class Key extends Model 'description' => 'List of SDK user agents that used this key.', 'default' => null, 'example' => 'appwrite:flutter', + 'array' => true ]) ; } From 4bced29ec90bc2a311a05dc1cdd923f764dbc0fe Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 01:36:36 +0530 Subject: [PATCH 04/75] feat: review comments --- app/controllers/general.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 5cdf0f4995..f8ccf2617b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -305,21 +305,21 @@ App::init() if (time() > $key->getAttribute('accessedAt', 0) + APP_KEY_USAGE) { $key->setAttribute('accessedAt', time()); $sdkValidator = new WhiteList([ - 'appwrite:nodejs', - 'appwrite:deno', - 'appwrite:php', - 'appwrite:python', - 'appwrite:ruby', - 'appwrite:go', - 'appwrite:java', - 'appwrite:dotnet', - 'appwrite:dart', - 'appwrite:kotlin', - 'appwrite:swift' + 'nodejs', + 'deno', + 'php', + 'python', + 'ruby', + 'go', + 'java', + 'dotnet', + 'dart', + 'kotlin', + 'swift' ], true); $sdk = $request->getHeader('x-sdk-version', 'UNKNOWN'); - $sdk = substr($sdk, 0, strrpos($sdk, ':')); + $sdk = explode(':', $sdk)[1] ?? 'UNKNOWN'; if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); From 7e470d2cb595db12537bc647d68c5d3c3d718e4f Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 10:54:17 +0530 Subject: [PATCH 05/75] feat: review comments --- app/controllers/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index f8ccf2617b..5010d14d44 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -319,7 +319,7 @@ App::init() ], true); $sdk = $request->getHeader('x-sdk-version', 'UNKNOWN'); - $sdk = explode(':', $sdk)[1] ?? 'UNKNOWN'; + $sdk = explode(':', $sdk)[1] ?? ''; if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); From 8cae6bb627bf949d7b7da321a5305ad012ed54bf Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 11:26:53 +0530 Subject: [PATCH 06/75] feat: review comments --- app/controllers/general.php | 2 +- app/init.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 5010d14d44..57b9a6f0f0 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -302,7 +302,7 @@ App::init() Authorization::setRole('role:' . Auth::USER_ROLE_APP); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - if (time() > $key->getAttribute('accessedAt', 0) + APP_KEY_USAGE) { + if (time() > $key->getAttribute('accessedAt', 0) + APP_KEY_ACCCESS) { $key->setAttribute('accessedAt', time()); $sdkValidator = new WhiteList([ 'nodejs', diff --git a/app/init.php b/app/init.php index d09b08a1d8..773b3041e7 100644 --- a/app/init.php +++ b/app/init.php @@ -88,7 +88,7 @@ const APP_LIMIT_COMPRESSION = 20000000; //20MB const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length. const APP_LIMIT_SUBQUERY = 1000; -const APP_KEY_USAGE = 24 * 60 * 60; // 24 hours +const APP_KEY_ACCCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 402; const APP_VERSION_STABLE = '0.15.3'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; From 410597eca7f503b75807f4f61b04d5fdf1074af1 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 11:35:25 +0530 Subject: [PATCH 07/75] feat: review comments --- app/controllers/general.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 57b9a6f0f0..c0ab47040a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -323,7 +323,9 @@ App::init() if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); - array_push($sdks, $sdk); + if (!in_array($sdk, $sdks)) { + array_push($sdks, $sdk); + } $key->setAttribute('sdks', $sdks); } From f26f2d9e9ba9509be29889226f83cd933fa5c0d7 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 11:43:34 +0530 Subject: [PATCH 08/75] feat: review comments --- app/controllers/general.php | 52 +++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index c0ab47040a..a8d7fa545a 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -304,34 +304,36 @@ App::init() if (time() > $key->getAttribute('accessedAt', 0) + APP_KEY_ACCCESS) { $key->setAttribute('accessedAt', time()); - $sdkValidator = new WhiteList([ - 'nodejs', - 'deno', - 'php', - 'python', - 'ruby', - 'go', - 'java', - 'dotnet', - 'dart', - 'kotlin', - 'swift' - ], true); - - $sdk = $request->getHeader('x-sdk-version', 'UNKNOWN'); - $sdk = explode(':', $sdk)[1] ?? ''; - - if ($sdkValidator->isValid($sdk)) { - $sdks = $key->getAttribute('sdks', []); - if (!in_array($sdk, $sdks)) { - array_push($sdks, $sdk); - } - $key->setAttribute('sdks', $sdks); - } - $dbForConsole->updateDocument('keys', $key->getId(), $key); $dbForConsole->deleteCachedDocument('projects', $project->getId()); } + + $sdkValidator = new WhiteList([ + 'nodejs', + 'deno', + 'php', + 'python', + 'ruby', + 'go', + 'java', + 'dotnet', + 'dart', + 'kotlin', + 'swift' + ], true); + + $sdk = $request->getHeader('x-sdk-version', 'UNKNOWN'); + $sdk = explode(':', $sdk)[1] ?? ''; + + if ($sdkValidator->isValid($sdk)) { + $sdks = $key->getAttribute('sdks', []); + if (!in_array($sdk, $sdks)) { + array_push($sdks, $sdk); + $key->setAttribute('sdks', $sdks); + $dbForConsole->updateDocument('keys', $key->getId(), $key); + $dbForConsole->deleteCachedDocument('projects', $project->getId()); + } + } } } From 21a3037bdf8aabf24957fe0273e0ee68c581be9c Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 9 Aug 2022 14:22:30 +0530 Subject: [PATCH 09/75] feat: review comments --- app/controllers/general.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index a8d7fa545a..cad63bbaf2 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -330,6 +330,9 @@ App::init() if (!in_array($sdk, $sdks)) { array_push($sdks, $sdk); $key->setAttribute('sdks', $sdks); + + /** Update access time as well */ + $key->setAttribute('accessedAt', time()); $dbForConsole->updateDocument('keys', $key->getId(), $key); $dbForConsole->deleteCachedDocument('projects', $project->getId()); } From 4f218ea6d36850487485489f79b98d8e4f4494db Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 10 Aug 2022 18:22:12 +0530 Subject: [PATCH 10/75] feat: add new mock endpoint for sdk generator tests --- app/controllers/mock.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/app/controllers/mock.php b/app/controllers/mock.php index d3b150a55f..c617e5e6fd 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -7,6 +7,7 @@ use Utopia\Database\Document; use Appwrite\Network\Validator\Host; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; use Utopia\App; use Utopia\Validator\ArrayList; use Utopia\Validator\Integer; @@ -395,6 +396,34 @@ App::get('/v1/mock/tests/general/empty') $response->noContent(); }); +App::get('/v1/mock/tests/general/headers') + ->desc('Get headers') + ->groups(['mock']) + ->label('scope', 'public') + ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) + ->label('sdk.namespace', 'general') + ->label('sdk.method', 'headers') + ->label('sdk.description', 'Return headers from the request') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk.mock', true) + ->inject('request') + ->inject('response') + ->action(function (Request $request, Response $response) { + $res = [ + 'x-sdk-name' => $request->getHeader('x-sdk-name'), + 'x-sdk-platform' => $request->getHeader('x-sdk-platform'), + 'x-sdk-language' => $request->getHeader('x-sdk-language'), + 'x-sdk-version' => $request->getHeader('x-sdk-version'), + ]; + $res = array_map(function ($key, $value) { + return $key . ': ' . $value; + }, array_keys($res), $res); + $res = implode("; ", $res); + + $response->dynamic(new Document(['result' => $res]), Response::MODEL_MOCK); + }); + App::get('/v1/mock/tests/general/400-error') ->desc('400 Error') ->groups(['mock']) From 9fe28e830ae37396831fe6bf1c2b63be484c463f Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 10 Aug 2022 18:30:57 +0530 Subject: [PATCH 11/75] feat: add platform to sdk generation script --- app/controllers/general.php | 3 +-- app/tasks/sdks.php | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index cad63bbaf2..27f93c5126 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -322,8 +322,7 @@ App::init() 'swift' ], true); - $sdk = $request->getHeader('x-sdk-version', 'UNKNOWN'); - $sdk = explode(':', $sdk)[1] ?? ''; + $sdk = $request->getHeader('x-sdk-name', 'UNKNOWN'); if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); diff --git a/app/tasks/sdks.php b/app/tasks/sdks.php index d873167743..b000cc7482 100644 --- a/app/tasks/sdks.php +++ b/app/tasks/sdks.php @@ -178,6 +178,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ->setLicense($license) ->setLicenseContent($licenseContent) ->setVersion($language['version']) + ->setPlatform($key) ->setGitURL($language['url']) ->setGitRepo($language['gitUrl']) ->setGitRepoName($language['gitRepoName']) From 42d78f9a68568e5d13261597585dfe6abc762221 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 10 Aug 2022 18:33:49 +0530 Subject: [PATCH 12/75] feat: update sdk generatoe dependency --- composer.json | 2 +- composer.lock | 38 ++++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index ca0f209496..d35cec8852 100644 --- a/composer.json +++ b/composer.json @@ -76,7 +76,7 @@ } ], "require-dev": { - "appwrite/sdk-generator": "0.19.5", + "appwrite/sdk-generator": "dev-feat-new-headers", "phpunit/phpunit": "9.5.20", "squizlabs/php_codesniffer": "^3.6", "swoole/ide-helper": "4.8.9", diff --git a/composer.lock b/composer.lock index 93b8455cac..d2bdf6b704 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": "0a8ed4fa28bf33ceb7396c35b9e8a155", + "content-hash": "5c846e4b9f655c018d30cad74cb5ecca", "packages": [ { "name": "adhocore/jwt", @@ -1894,16 +1894,16 @@ }, { "name": "utopia-php/cache", - "version": "0.6.0", + "version": "0.6.1", "source": { "type": "git", "url": "https://github.com/utopia-php/cache.git", - "reference": "8ea1353a4bbab617e23c865a7c97b60d8074aee3" + "reference": "9889235a6d3da6cbb1f435201529da4d27c30e79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cache/zipball/8ea1353a4bbab617e23c865a7c97b60d8074aee3", - "reference": "8ea1353a4bbab617e23c865a7c97b60d8074aee3", + "url": "https://api.github.com/repos/utopia-php/cache/zipball/9889235a6d3da6cbb1f435201529da4d27c30e79", + "reference": "9889235a6d3da6cbb1f435201529da4d27c30e79", "shasum": "" }, "require": { @@ -1941,9 +1941,9 @@ ], "support": { "issues": "https://github.com/utopia-php/cache/issues", - "source": "https://github.com/utopia-php/cache/tree/0.6.0" + "source": "https://github.com/utopia-php/cache/tree/0.6.1" }, - "time": "2022-04-04T12:30:05+00:00" + "time": "2022-08-10T08:12:46+00:00" }, { "name": "utopia-php/cli", @@ -2828,29 +2828,29 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.19.5", + "version": "dev-feat-new-headers", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "04de540cf683e2b08b3192c137dde7f2c37003d9" + "reference": "3203428b4139e0ac2c0e46f1e5dff11c6a084f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/04de540cf683e2b08b3192c137dde7f2c37003d9", - "reference": "04de540cf683e2b08b3192c137dde7f2c37003d9", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/3203428b4139e0ac2c0e46f1e5dff11c6a084f17", + "reference": "3203428b4139e0ac2c0e46f1e5dff11c6a084f17", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "matthiasmullie/minify": "^1.3", + "matthiasmullie/minify": "^1.3.68", "php": ">=7.0.0", - "twig/twig": "^3.3" + "twig/twig": "^3.4.1" }, "require-dev": { "brianium/paratest": "^6.4", - "phpunit/phpunit": "^9.5.13" + "phpunit/phpunit": "^9.5.21" }, "type": "library", "autoload": { @@ -2872,9 +2872,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.19.5" + "source": "https://github.com/appwrite/sdk-generator/tree/feat-new-headers" }, - "time": "2022-07-06T11:05:57+00:00" + "time": "2022-08-10T12:49:12+00:00" }, { "name": "doctrine/instantiator", @@ -5348,7 +5348,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "appwrite/sdk-generator": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -5370,5 +5372,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } From 741824ef87f8485f9259344ec6b69b76123270dd Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 10 Aug 2022 19:15:04 +0530 Subject: [PATCH 13/75] feat: move server list to app resource --- app/controllers/general.php | 19 +++---------------- app/init.php | 11 +++++++++++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 27f93c5126..1446d210b4 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -46,7 +46,8 @@ App::init() ->inject('user') ->inject('locale') ->inject('clients') - ->action(function (App $utopia, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $clients) { + ->inject('servers') + ->action(function (App $utopia, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, Document $user, Locale $locale, array $clients, array $servers) { /* * Request format */ @@ -308,22 +309,8 @@ App::init() $dbForConsole->deleteCachedDocument('projects', $project->getId()); } - $sdkValidator = new WhiteList([ - 'nodejs', - 'deno', - 'php', - 'python', - 'ruby', - 'go', - 'java', - 'dotnet', - 'dart', - 'kotlin', - 'swift' - ], true); - + $sdkValidator = new WhiteList($servers, true); $sdk = $request->getHeader('x-sdk-name', 'UNKNOWN'); - if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); if (!in_array($sdk, $sdks)) { diff --git a/app/init.php b/app/init.php index 773b3041e7..8d49d89aba 100644 --- a/app/init.php +++ b/app/init.php @@ -998,3 +998,14 @@ App::setResource('phone', function () { default => null }; }); + +App::setResource('servers', function () { + $platforms = Config::getParam('platforms'); + $server = $platforms[APP_PLATFORM_SERVER]; + + $languages = array_map(function ($language) { + return strtolower($language['name']); + }, $server['languages']); + + return $languages; +}); \ No newline at end of file From b4e944e9ba97a172eb3ad2e4810823cf4d0c1343 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Wed, 10 Aug 2022 19:19:56 +0530 Subject: [PATCH 14/75] feat: run linter --- app/controllers/general.php | 4 ++-- app/controllers/mock.php | 2 +- app/init.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 1446d210b4..f9db2584ad 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -314,9 +314,9 @@ App::init() if ($sdkValidator->isValid($sdk)) { $sdks = $key->getAttribute('sdks', []); if (!in_array($sdk, $sdks)) { - array_push($sdks, $sdk); + array_push($sdks, $sdk); $key->setAttribute('sdks', $sdks); - + /** Update access time as well */ $key->setAttribute('accessedAt', time()); $dbForConsole->updateDocument('keys', $key->getId(), $key); diff --git a/app/controllers/mock.php b/app/controllers/mock.php index c617e5e6fd..f2b7de9793 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -420,7 +420,7 @@ App::get('/v1/mock/tests/general/headers') return $key . ': ' . $value; }, array_keys($res), $res); $res = implode("; ", $res); - + $response->dynamic(new Document(['result' => $res]), Response::MODEL_MOCK); }); diff --git a/app/init.php b/app/init.php index 8d49d89aba..d0747e5bc7 100644 --- a/app/init.php +++ b/app/init.php @@ -1008,4 +1008,4 @@ App::setResource('servers', function () { }, $server['languages']); return $languages; -}); \ No newline at end of file +}); From cd5f3f2f2bb54cf5e49252de57d95cfcfe93880d Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 11 Aug 2022 00:00:59 +0530 Subject: [PATCH 15/75] feat: update mock endpoint spec --- app/controllers/mock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/mock.php b/app/controllers/mock.php index f2b7de9793..8aed4bc95a 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -405,7 +405,7 @@ App::get('/v1/mock/tests/general/headers') ->label('sdk.method', 'headers') ->label('sdk.description', 'Return headers from the request') ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk.response.model', Response::MODEL_MOCK) ->label('sdk.mock', true) ->inject('request') ->inject('response') From f09cce93ee6f6e2dc0c748b774e6f18f403118ca Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 09:37:35 +0000 Subject: [PATCH 16/75] feat: use datetime filters for acessedAt --- app/config/collections.php | 6 +++--- composer.lock | 22 +++++++--------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 2d37884169..a6024bd0a0 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -977,7 +977,7 @@ $collections = [ ], [ '$id' => 'accessedAt', - 'type' => Database::VAR_INTEGER, + 'type' => Database::, 'format' => '', 'size' => 0, 'signed' => false, @@ -2847,14 +2847,14 @@ $collections = [ ], [ '$id' => 'accessedAt', - 'type' => Database::VAR_INTEGER, + 'type' => Database::VAR_DATETIME, 'format' => '', 'size' => 0, 'signed' => false, 'required' => true, 'default' => null, 'array' => false, - 'filters' => [], + 'filters' => ['datetime'], ], [ '$id' => 'signature', diff --git a/composer.lock b/composer.lock index df54b90a35..831d28ec1c 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": "5c846e4b9f655c018d30cad74cb5ecca", + "content-hash": "d404d30f1318f2b9a9171acdef966900", "packages": [ { "name": "adhocore/jwt", @@ -2833,12 +2833,12 @@ "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "3203428b4139e0ac2c0e46f1e5dff11c6a084f17" + "reference": "034ee359ba97c0d5a4727639463b645802332bf6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/3203428b4139e0ac2c0e46f1e5dff11c6a084f17", - "reference": "3203428b4139e0ac2c0e46f1e5dff11c6a084f17", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/034ee359ba97c0d5a4727639463b645802332bf6", + "reference": "034ee359ba97c0d5a4727639463b645802332bf6", "shasum": "" }, "require": { @@ -2853,7 +2853,6 @@ "brianium/paratest": "^6.4", "phpunit/phpunit": "^9.5.21" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2876,7 +2875,7 @@ "issues": "https://github.com/appwrite/sdk-generator/issues", "source": "https://github.com/appwrite/sdk-generator/tree/feat-new-headers" }, - "time": "2022-08-10T12:49:12+00:00" + "time": "2022-08-19T09:16:17+00:00" }, { "name": "doctrine/instantiator", @@ -5348,14 +5347,7 @@ "time": "2022-08-12T06:47:24+00:00" } ], - "aliases": [ - { - "package": "appwrite/sdk-generator", - "version": "9999999-dev", - "alias": "0.19.5", - "alias_normalized": "0.19.5.0" - } - ], + "aliases": [], "minimum-stability": "stable", "stability-flags": { "appwrite/sdk-generator": 20 @@ -5383,5 +5375,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } From e104f553cbd84a9de2137afd368e716b7db9de81 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 09:41:22 +0000 Subject: [PATCH 17/75] feat: use datetime filters for acessedAt --- app/config/collections.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index a6024bd0a0..9b030f6f67 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -977,14 +977,14 @@ $collections = [ ], [ '$id' => 'accessedAt', - 'type' => Database::, + 'type' => Database::VAR_DATETIME, 'format' => '', 'size' => 0, 'signed' => false, 'required' => false, 'default' => 0, 'array' => false, - 'filters' => [], + 'filters' => ['datetime'], ], [ '$id' => 'sdks', @@ -2847,14 +2847,14 @@ $collections = [ ], [ '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, + 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, 'signed' => false, 'required' => true, 'default' => null, 'array' => false, - 'filters' => ['datetime'], + 'filters' => [], ], [ '$id' => 'signature', From 28d9e159808c5aed4ba05defe931c166c188ef98 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 09:45:36 +0000 Subject: [PATCH 18/75] feat: update response model --- src/Appwrite/Utopia/Response/Model/Key.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 5a5fefa8fd..501510c456 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -59,10 +59,11 @@ class Key extends Model 'example' => '919c2d18fb5d4...a2ae413da83346ad2', ]) ->addRule('accessedAt', [ - 'type' => self::TYPE_INTEGER, + 'type' => self::TYPE_DATETIME_EXAMPLE, 'description' => 'Most recent access date in Unix timestamp.', 'default' => null, - 'example' => '1653990687', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE ]) ->addRule('sdks', [ 'type' => self::TYPE_STRING, From 74a5bd25564125a2571456d1a8fd4e543e87246f Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 09:54:26 +0000 Subject: [PATCH 19/75] feat: update default values --- app/config/collections.php | 4 ++-- app/controllers/api/projects.php | 2 +- app/controllers/mock.php | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 9b030f6f67..428609365c 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -976,13 +976,13 @@ $collections = [ 'filters' => ['datetime'], ], [ - '$id' => 'accessedAt', + '$id' => ID::custom('accessedAt'), 'type' => Database::VAR_DATETIME, 'format' => '', 'size' => 0, 'signed' => false, 'required' => false, - 'default' => 0, + 'default' => null, 'array' => false, 'filters' => ['datetime'], ], diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index d220964a52..d23349c10f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -866,7 +866,7 @@ App::post('/v1/projects/:projectId/keys') 'scopes' => $scopes, 'expire' => $expire, 'sdks' => [], - 'accessedAt' => 0, + 'accessedAt' => null, 'secret' => \bin2hex(\random_bytes(128)), ]); diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 5473af6491..80b9a4f0ac 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -396,6 +396,7 @@ App::get('/v1/mock/tests/general/empty') $response->noContent(); }); +/** Endpoint to test if required headers are sent from the SDK */ App::get('/v1/mock/tests/general/headers') ->desc('Get headers') ->groups(['mock']) From dbd7afeda0b09801fdfce312de265559fcf65cf7 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 09:58:11 +0000 Subject: [PATCH 20/75] feat: update default values --- app/config/collections.php | 2 +- src/Appwrite/Utopia/Response/Model/Key.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 428609365c..36f6761677 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -987,7 +987,7 @@ $collections = [ 'filters' => ['datetime'], ], [ - '$id' => 'sdks', + '$id' => ID::custom('sdks'), 'type' => Database::VAR_STRING, 'format' => '', 'size' => Database::LENGTH_KEY, diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index 501510c456..e5879d2934 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -62,7 +62,6 @@ class Key extends Model 'type' => self::TYPE_DATETIME_EXAMPLE, 'description' => 'Most recent access date in Unix timestamp.', 'default' => null, - 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE ]) ->addRule('sdks', [ From 7673fb44e576c07c6c62b9f600b1d8e4413985e6 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 10:03:54 +0000 Subject: [PATCH 21/75] feat: update default values --- src/Appwrite/Utopia/Response/Model/Key.php | 4 ++-- src/Appwrite/Utopia/Response/Model/User.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Key.php b/src/Appwrite/Utopia/Response/Model/Key.php index e5879d2934..d404db72d1 100644 --- a/src/Appwrite/Utopia/Response/Model/Key.php +++ b/src/Appwrite/Utopia/Response/Model/Key.php @@ -59,9 +59,9 @@ class Key extends Model 'example' => '919c2d18fb5d4...a2ae413da83346ad2', ]) ->addRule('accessedAt', [ - 'type' => self::TYPE_DATETIME_EXAMPLE, + 'type' => self::TYPE_DATETIME, 'description' => 'Most recent access date in Unix timestamp.', - 'default' => null, + 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE ]) ->addRule('sdks', [ diff --git a/src/Appwrite/Utopia/Response/Model/User.php b/src/Appwrite/Utopia/Response/Model/User.php index 2c6cccbdd0..4462fe63f0 100644 --- a/src/Appwrite/Utopia/Response/Model/User.php +++ b/src/Appwrite/Utopia/Response/Model/User.php @@ -65,7 +65,7 @@ class User extends Model ->addRule('registration', [ 'type' => self::TYPE_DATETIME, 'description' => 'User registration date in Datetime.', - 'default' => null, + 'default' => '', 'example' => self::TYPE_DATETIME_EXAMPLE, ]) ->addRule('status', [ From 926d1c64599e4aa2e4f167c2c4e08f928672858a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Fri, 19 Aug 2022 14:14:39 +0000 Subject: [PATCH 22/75] Fix incorrect endpoint information --- app/controllers/api/databases.php | 6 +++--- docs/references/databases/get-logs.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 docs/references/databases/get-logs.md diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 321f3c5829..795527600d 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -315,13 +315,13 @@ App::get('/v1/databases/:databaseId') }); App::get('/v1/databases/:databaseId/logs') - ->desc('List Collection Logs') + ->desc('List Database Logs') ->groups(['api', 'database']) - ->label('scope', 'collections.read') + ->label('scope', 'databases.read') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'databases') ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/databases/get-collection-logs.md') + ->label('sdk.description', '/docs/references/databases/get-logs.md') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_LOG_LIST) diff --git a/docs/references/databases/get-logs.md b/docs/references/databases/get-logs.md new file mode 100644 index 0000000000..8e49da4603 --- /dev/null +++ b/docs/references/databases/get-logs.md @@ -0,0 +1 @@ +Get the database activity logs list by its unique ID. \ No newline at end of file From ca25d329aeb5bcba3715c483facb4c09aa8c5183 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 19 Aug 2022 20:22:38 +0530 Subject: [PATCH 23/75] feat: update date time calculation --- app/controllers/general.php | 7 ++++--- composer.lock | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index a1f9450a1b..0a046185d2 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -306,8 +306,9 @@ App::init() Authorization::setRole(Auth::USER_ROLE_APPS); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - if (time() > $key->getAttribute('accessedAt', 0) + APP_KEY_ACCCESS) { - $key->setAttribute('accessedAt', time()); + $accessedAt = $key->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCCESS)) > $accessedAt) { + $key->setAttribute('accessedAt', DateTime::now()); $dbForConsole->updateDocument('keys', $key->getId(), $key); $dbForConsole->deleteCachedDocument('projects', $project->getId()); } @@ -321,7 +322,7 @@ App::init() $key->setAttribute('sdks', $sdks); /** Update access time as well */ - $key->setAttribute('accessedAt', time()); + $key->setAttribute('accessedAt', Datetime::now()); $dbForConsole->updateDocument('keys', $key->getId(), $key); $dbForConsole->deleteCachedDocument('projects', $project->getId()); } diff --git a/composer.lock b/composer.lock index 831d28ec1c..8864cd1c62 100644 --- a/composer.lock +++ b/composer.lock @@ -5375,5 +5375,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } From 7952dac85e4cac5904c1eced2076fd217a88136a Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Sat, 20 Aug 2022 07:41:07 +0000 Subject: [PATCH 24/75] feat: linter fixes --- app/controllers/general.php | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 0a046185d2..221e69678b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -306,7 +306,7 @@ App::init() Authorization::setRole(Auth::USER_ROLE_APPS); Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - $accessedAt = $key->getAttribute('accessedAt', ''); + $accessedAt = $key->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCCESS)) > $accessedAt) { $key->setAttribute('accessedAt', DateTime::now()); $dbForConsole->updateDocument('keys', $key->getId(), $key); diff --git a/composer.lock b/composer.lock index 8864cd1c62..f9221fb8a5 100644 --- a/composer.lock +++ b/composer.lock @@ -3525,23 +3525,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.15", + "version": "9.2.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" + "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2593003befdcc10db5e213f9f28814f5aa8ac073", + "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^4.14", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -3590,7 +3590,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.16" }, "funding": [ { @@ -3598,7 +3598,7 @@ "type": "github" } ], - "time": "2022-03-07T09:28:20+00:00" + "time": "2022-08-20T05:26:47+00:00" }, { "name": "phpunit/php-file-iterator", From da73dc7fcb4b621bf94bda61834ad4d275a4c785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 08:37:31 +0000 Subject: [PATCH 25/75] Fix users queries allowed params --- src/Appwrite/Utopia/Database/Validator/Queries/Users.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php index ffe30f1209..76321394c1 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php @@ -7,6 +7,10 @@ use Appwrite\Utopia\Database\Validator\Queries\Collection; class Users extends Collection { public const ALLOWED_ATTRIBUTES = [ + '$id', + '$createdAt', + '$updatedAt', + 'name', 'email', 'phone', @@ -14,8 +18,7 @@ class Users extends Collection 'passwordUpdate', 'registration', 'emailVerification', - 'phoneVerification', - 'search', + 'phoneVerification' ]; /** From 6fcd3757fef4cc5625aa735d1e37c34bae45b24e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 08:37:55 +0000 Subject: [PATCH 26/75] Upgrade listBuckets queries --- app/controllers/api/storage.php | 38 ++++++++++--------- .../Database/Validator/Queries/Buckets.php | 30 +++++++++++++++ 2 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index de69bd1351..4920ba92bd 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -25,6 +25,7 @@ use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Appwrite\Extend\Exception; +use Appwrite\Utopia\Database\Validator\Queries\Buckets; use Utopia\Image\Image; use Utopia\Storage\Compression\Algorithms\GZIP; use Utopia\Storage\Device; @@ -154,41 +155,42 @@ App::get('/v1/storage/buckets') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_BUCKET_LIST) + ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('cursor', '', new UID(), 'ID of the bucket used as the starting point for the query, excluding the bucket itself. Should be used for efficient pagination when working with large sets of data.', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { - - $filterQueries = []; + ->action(function (array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { + + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('name', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === Database::ORDER_ASC ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('buckets', $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $bucketId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('buckets', $bucketId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Bucket '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Bucket '{$bucketId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } + $filterQueries = Query::groupByType($queries)['filters']; + $usage->setParam('storage.buckets.read', 1); $response->dynamic(new Document([ - 'buckets' => $dbForProject->find('buckets', \array_merge($filterQueries, $queries)), + 'buckets' => $dbForProject->find('buckets', $queries), 'total' => $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_BUCKET_LIST); }); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php new file mode 100644 index 0000000000..e14b74ea3d --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -0,0 +1,30 @@ + Date: Tue, 23 Aug 2022 08:49:39 +0000 Subject: [PATCH 27/75] Upgrade listFiles queries --- app/controllers/api/storage.php | 38 ++++++++++--------- .../Database/Validator/Queries/Files.php | 30 +++++++++++++++ 2 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Files.php diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 4920ba92bd..1e472815fc 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -26,6 +26,7 @@ use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Validator\Queries\Buckets; +use Appwrite\Utopia\Database\Validator\Queries\Files; use Utopia\Image\Image; use Utopia\Storage\Compression\Algorithms\GZIP; use Utopia\Storage\Device; @@ -684,17 +685,13 @@ App::get('/v1/storage/buckets/:bucketId/files') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_FILE_LIST) ->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).') + ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of files to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the file used as the starting point for the query, excluding the file itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') ->inject('usage') ->inject('mode') - ->action(function (string $bucketId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage, string $mode) { + ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, Stats $usage, string $mode) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); @@ -707,31 +704,36 @@ App::get('/v1/storage/buckets/:bucketId/files') throw new Exception(Exception::USER_UNAUTHORIZED); } - $filterQueries = []; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('name', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === Database::ORDER_ASC ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $fileId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "File '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "File '{$fileId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } + $filterQueries = Query::groupByType($queries)['filters']; + if ($bucket->getAttribute('fileSecurity', false)) { - $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), \array_merge($filterQueries, $queries)); + $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), \array_merge($filterQueries, $queries))); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php new file mode 100644 index 0000000000..1fb9b39c5a --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php @@ -0,0 +1,30 @@ + Date: Tue, 23 Aug 2022 08:56:28 +0000 Subject: [PATCH 28/75] Upgrade listTeams queries --- app/controllers/api/teams.php | 36 ++++++++++--------- .../Database/Validator/Queries/Teams.php | 26 ++++++++++++++ 2 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Teams.php diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index f20f90049d..47c4b3e7cb 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -10,6 +10,7 @@ use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Host; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Database\Validator\Queries\Teams; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -122,37 +123,38 @@ App::get('/v1/teams') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_TEAM_LIST) + ->param('queries', [], new Teams(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of teams to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the team used as the starting point for the query, excluding the team itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $filterQueries = []; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === Database::ORDER_ASC ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('teams', $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $teamId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('teams', $teamId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Team '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Team '{$teamId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } - $results = $dbForProject->find('teams', \array_merge($filterQueries, $queries)); + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('teams', $queries); $total = $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT); $response->dynamic(new Document([ diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php new file mode 100644 index 0000000000..7aae93f65a --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php @@ -0,0 +1,26 @@ + Date: Tue, 23 Aug 2022 09:02:06 +0000 Subject: [PATCH 29/75] Upgrade listFunctions queries --- app/controllers/api/functions.php | 36 ++++++++++--------- .../Database/Validator/Queries/Functions.php | 32 +++++++++++++++++ 2 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Functions.php diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 2c38a529eb..9f79d77f93 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -22,6 +22,7 @@ use Utopia\Storage\Validator\Upload; use Appwrite\Utopia\Response; use Utopia\Swoole\Request; use Appwrite\Task\Validator\Cron; +use Appwrite\Utopia\Database\Validator\Queries\Functions; use Utopia\App; use Utopia\Database\Database; use Utopia\Database\Document; @@ -102,38 +103,39 @@ App::get('/v1/functions') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_FUNCTION_LIST) + ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Functions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of functions to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the function used as the starting point for the query, excluding the function itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - $filterQueries = []; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === Database::ORDER_ASC ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('functions', $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $functionId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('functions', $functionId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Function '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Function '{$functionId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ - 'functions' => $dbForProject->find('functions', \array_merge($filterQueries, $queries)), + 'functions' => $dbForProject->find('functions', $queries), 'total' => $dbForProject->count('functions', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_FUNCTION_LIST); }); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php new file mode 100644 index 0000000000..8a08a8371a --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php @@ -0,0 +1,32 @@ + Date: Tue, 23 Aug 2022 09:12:48 +0000 Subject: [PATCH 30/75] Upgrade listDeployments queries --- app/controllers/api/functions.php | 41 ++++++++++--------- .../Validator/Queries/Deployments.php | 29 +++++++++++++ 2 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 9f79d77f93..ace753e938 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -22,6 +22,7 @@ use Utopia\Storage\Validator\Upload; use Appwrite\Utopia\Response; use Utopia\Swoole\Request; use Appwrite\Task\Validator\Cron; +use Appwrite\Utopia\Database\Validator\Queries\Deployments; use Appwrite\Utopia\Database\Validator\Queries\Functions; use Utopia\App; use Utopia\Database\Database; @@ -662,15 +663,11 @@ App::get('/v1/functions/:functionId/deployments') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST) ->param('functionId', '', new UID(), 'Function ID.') + ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of deployments to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the deployment used as the starting point for the query, excluding the deployment itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $functionId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { + ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject) { $function = $dbForProject->getDocument('functions', $functionId); @@ -678,30 +675,36 @@ App::get('/v1/functions/:functionId/deployments') throw new Exception(Exception::FUNCTION_NOT_FOUND); } - $filterQueries = []; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $filterQueries[] = Query::equal('resourceId', [$function->getId()]); - $filterQueries[] = Query::equal('resourceType', ['functions']); + // Set default limit + $queries[] = Query::limit(25); - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === Database::ORDER_ASC ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('deployments', $cursor); + // Set resource queries + $queries[] = Query::equal('resourceId', [$function->getId()]); + $queries[] = Query::equal('resourceType', ['functions']); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $deploymentId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('deployments', $deploymentId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Tag '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Deployment '{$deploymentId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } - $results = $dbForProject->find('deployments', \array_merge($filterQueries, $queries)); + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('deployments', $queries); $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); foreach ($results as $result) { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php new file mode 100644 index 0000000000..2d4e2ca32d --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -0,0 +1,29 @@ + Date: Tue, 23 Aug 2022 09:26:34 +0000 Subject: [PATCH 31/75] Upgrade listExecutions queries --- app/controllers/api/functions.php | 40 ++++++++++--------- .../Database/Validator/Queries/Executions.php | 28 +++++++++++++ 2 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Executions.php diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index ace753e938..81be96d7ea 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -23,6 +23,7 @@ use Appwrite\Utopia\Response; use Utopia\Swoole\Request; use Appwrite\Task\Validator\Cron; use Appwrite\Utopia\Database\Validator\Queries\Deployments; +use Appwrite\Utopia\Database\Validator\Queries\Executions; use Appwrite\Utopia\Database\Validator\Queries\Functions; use Utopia\App; use Utopia\Database\Database; @@ -1023,14 +1024,11 @@ App::get('/v1/functions/:functionId/executions') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_EXECUTION_LIST) ->param('functionId', '', new UID(), 'Function ID.') - ->param('limit', 25, new Range(0, 100), 'Maximum number of executions to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) + ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Executions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('cursor', '', new UID(), 'ID of the execution used as the starting point for the query, excluding the execution itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $functionId, int $limit, int $offset, string $search, string $cursor, string $cursorDirection, Response $response, Database $dbForProject) { + ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject) { $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); @@ -1038,29 +1036,35 @@ App::get('/v1/functions/:functionId/executions') throw new Exception(Exception::FUNCTION_NOT_FOUND); } - $filterQueries = [ - Query::equal('functionId', [$function->getId()]) - ]; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('executions', $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Set internal queries + $queries[] = Query::equal('functionId', [$function->getId()]); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $executionId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('executions', $executionId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Tag '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Execution '{$executionId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } - $results = $dbForProject->find('executions', \array_merge($filterQueries, $queries)); + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('executions', $queries); $total = $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT); $roles = Authorization::getRoles(); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php new file mode 100644 index 0000000000..b53fda8f18 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php @@ -0,0 +1,28 @@ + Date: Tue, 23 Aug 2022 09:40:17 +0000 Subject: [PATCH 32/75] Upgrade listDatabases queries --- app/controllers/api/databases.php | 36 ++++++++++--------- .../Database/Validator/Queries/Databases.php | 25 +++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Databases.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index d2fd3b9fdd..716c74f7ff 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -48,6 +48,7 @@ use Appwrite\Detector\Detector; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Stats\Stats; +use Appwrite\Utopia\Database\Validator\Queries\Databases; use Utopia\Config\Config; use MaxMind\Db\Reader; @@ -239,41 +240,42 @@ App::get('/v1/databases') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_DATABASE_LIST) + ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of collection to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the collection used as the starting point for the query, excluding the collection itself. Should be used for efficient pagination when working with large sets of data.', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function (string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { - $filterQueries = []; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === 'ASC' ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('databases', $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $databaseId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('databases', $databaseId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Database '{$databaseId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } $usage->setParam('databases.read', 1); + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ - 'databases' => $dbForProject->find('databases', \array_merge($filterQueries, $queries)), + 'databases' => $dbForProject->find('databases', $queries), 'total' => $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_DATABASE_LIST); }); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php new file mode 100644 index 0000000000..8fee0492eb --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php @@ -0,0 +1,25 @@ + Date: Tue, 23 Aug 2022 12:30:28 +0000 Subject: [PATCH 33/75] Upgrade listCollections queries --- app/controllers/api/databases.php | 42 +++++++++---------- .../Validator/Queries/Collections.php | 27 ++++++++++++ 2 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Collections.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 716c74f7ff..f1ecfdeabe 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -48,6 +48,7 @@ use Appwrite\Detector\Detector; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Stats\Stats; +use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; use Utopia\Config\Config; use MaxMind\Db\Reader; @@ -270,10 +271,10 @@ App::get('/v1/databases') $cursor->setValue($cursorDocument); } - $usage->setParam('databases.read', 1); - $filterQueries = Query::groupByType($queries)['filters']; + $usage->setParam('databases.read', 1); + $response->dynamic(new Document([ 'databases' => $dbForProject->find('databases', $queries), 'total' => $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT), @@ -562,16 +563,12 @@ App::get('/v1/databases/:databaseId/collections') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_COLLECTION_LIST) ->param('databaseId', '', new UID(), 'Database ID.') + ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of collection to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the collection used as the starting point for the query, excluding the collection itself. Should be used for efficient pagination when working with large sets of data.', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') ->inject('usage') - ->action(function (string $databaseId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -579,34 +576,37 @@ App::get('/v1/databases/:databaseId/collections') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $filterQueries = []; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $queries = []; - $queries[] = Query::limit($limit); - $queries[] = Query::offset($offset); - $queries[] = $orderType === 'ASC' ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $collectionId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); } - $queries[] = $cursorDirection === Database::CURSOR_AFTER - ? Query::cursorAfter($cursorDocument) - : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } + $filterQueries = Query::groupByType($queries)['filters']; + $usage ->setParam('databaseId', $databaseId) ->setParam('databases.collections.read', 1); $response->dynamic(new Document([ - 'collections' => $dbForProject->find('database_' . $database->getInternalId(), \array_merge($filterQueries, $queries)), + 'collections' => $dbForProject->find('database_' . $database->getInternalId(), $queries), 'total' => $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_COLLECTION_LIST); }); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php new file mode 100644 index 0000000000..b429a1b744 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php @@ -0,0 +1,27 @@ + Date: Tue, 23 Aug 2022 12:50:52 +0000 Subject: [PATCH 34/75] Upgrade teamListLogs queries --- app/controllers/api/teams.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 47c4b3e7cb..1c53152eeb 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -10,7 +10,10 @@ use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Host; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Teams; +use Appwrite\Utopia\Database\Validator\Query\Limit; +use Appwrite\Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -857,18 +860,12 @@ App::get('/v1/teams/:teamId/logs') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_LOG_LIST) ->param('teamId', null, new UID(), 'Team ID.') - ->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) + ->param('queries', [], new Queries(new Limit(), new Offset()), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Only supported methods are limit and offset', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function ($teamId, $limit, $offset, $response, $dbForProject, $locale, $geodb) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Locale\Locale $locale */ - /** @var MaxMind\Db\Reader $geodb */ + ->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $team = $dbForProject->getDocument('teams', $teamId); @@ -876,6 +873,11 @@ App::get('/v1/teams/:teamId/logs') throw new Exception(Exception::TEAM_NOT_FOUND); } + $queries = Query::parseQueries($queries); + $grouped = Query::groupByType($queries); + $limit = $grouped['limit'] ?? 25; + $offset = $grouped['offset'] ?? 0; + $audit = new Audit($dbForProject); $resource = 'team/' . $team->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); From 36903d6358ead32adecc70e4c71b9841001dca6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 13:03:38 +0000 Subject: [PATCH 35/75] Upgrade document&collection&database logs queries --- app/controllers/api/databases.php | 54 ++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f1ecfdeabe..415a575b6a 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -38,16 +38,17 @@ use Appwrite\Network\Validator\IP; use Appwrite\Network\Validator\URL; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\IndexedQueries; -use Appwrite\Utopia\Database\Validator\Query\Cursor as CursorQueryValidator; -use Appwrite\Utopia\Database\Validator\Query\Filter as FilterQueryValidator; -use Appwrite\Utopia\Database\Validator\Query\Limit as LimitQueryValidator; -use Appwrite\Utopia\Database\Validator\Query\Offset as OffsetQueryValidator; -use Appwrite\Utopia\Database\Validator\Query\Order as OrderQueryValidator; +use Appwrite\Utopia\Database\Validator\Query\Cursor as Cursor; +use Appwrite\Utopia\Database\Validator\Query\Filter as Filter; +use Appwrite\Utopia\Database\Validator\Query\Limit as Limit; +use Appwrite\Utopia\Database\Validator\Query\Offset as Offset; +use Appwrite\Utopia\Database\Validator\Query\Order as Order; use Appwrite\Utopia\Response; use Appwrite\Detector\Detector; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; use Appwrite\Stats\Stats; +use Appwrite\Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; use Utopia\Config\Config; @@ -321,13 +322,12 @@ App::get('/v1/databases/:databaseId/logs') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_LOG_LIST) ->param('databaseId', '', new UID(), 'Database ID.') - ->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) + ->param('queries', [], new Queries(new Limit(), new Offset()), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Only supported methods are limit and offset', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $databaseId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $database = $dbForProject->getDocument('databases', $databaseId); @@ -335,9 +335,17 @@ App::get('/v1/databases/:databaseId/logs') throw new Exception(Exception::DATABASE_NOT_FOUND); } + $queries = Query::parseQueries($queries); + $grouped = Query::groupByType($queries); + $limit = $grouped['limit'] ?? 25; + $offset = $grouped['offset'] ?? 0; + $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId; $logs = $audit->getLogsByResource($resource, $limit, $offset); + + $output = []; + foreach ($logs as $i => &$log) { $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN'; @@ -663,13 +671,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ->label('sdk.response.model', Response::MODEL_LOG_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') - ->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) + ->param('queries', [], new Queries(new Limit(), new Offset()), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Only supported methods are limit and offset', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $databaseId, string $collectionId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -683,6 +690,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::COLLECTION_NOT_FOUND); } + $queries = Query::parseQueries($queries); + $grouped = Query::groupByType($queries); + $limit = $grouped['limit'] ?? 25; + $offset = $grouped['offset'] ?? 0; + $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId . '/collection/' . $collectionId; $logs = $audit->getLogsByResource($resource, $limit, $offset); @@ -2057,11 +2069,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $validator = new IndexedQueries( $attributes, $collection->getAttribute('indexes', []), - new CursorQueryValidator(), - new FilterQueryValidator($attributes), - new LimitQueryValidator(), - new OffsetQueryValidator(), - new OrderQueryValidator(), + new Cursor(), + new Filter($attributes), + new Limit(), + new Offset(), + new Order(), ); if (!$validator->isValid($queries)) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); @@ -2201,13 +2213,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', null, new UID(), 'Document ID.') - ->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) + ->param('queries', [], new Queries(new Limit(), new Offset()), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Only supported methods are limit and offset', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $databaseId, string $collectionId, string $documentId, int $limit, int $offset, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2226,6 +2237,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DOCUMENT_NOT_FOUND); } + $queries = Query::parseQueries($queries); + $grouped = Query::groupByType($queries); + $limit = $grouped['limit'] ?? 25; + $offset = $grouped['offset'] ?? 0; + $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); From b1348dbdd8024e7322e7bfc2e5f4cfe1b48894f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 13:06:59 +0000 Subject: [PATCH 36/75] Upgrade account logs queries --- app/controllers/api/account.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 5e70c244d5..4f321e2818 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -19,6 +19,9 @@ use Appwrite\Stats\Stats; use Appwrite\Template\Template; use Appwrite\URL\URL as URLParser; use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Database\Validator\Queries; +use Appwrite\Utopia\Database\Validator\Query\Limit; +use Appwrite\Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -1360,16 +1363,20 @@ App::get('/v1/account/logs') ->label('sdk.response.code', Response::STATUS_CODE_OK) ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_LOG_LIST) - ->param('limit', 25, new Range(0, 100), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) + ->param('queries', [], new Queries(new Limit(), new Offset()), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Only supported methods are limit and offset', true) ->inject('response') ->inject('user') ->inject('locale') ->inject('geodb') ->inject('dbForProject') ->inject('usage') - ->action(function (int $limit, int $offset, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject, Stats $usage) { + ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject, Stats $usage) { + $queries = Query::parseQueries($queries); + $grouped = Query::groupByType($queries); + $limit = $grouped['limit'] ?? 25; + $offset = $grouped['offset'] ?? 0; + $audit = new EventAudit($dbForProject); $logs = $audit->getLogsByUser($user->getId(), $limit, $offset); From 2d82eed4be770e6cc86c06bc3a2e86ecde98c0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 13:10:27 +0000 Subject: [PATCH 37/75] Linter fix --- app/controllers/api/account.php | 2 +- app/controllers/api/databases.php | 2 +- app/controllers/api/storage.php | 2 +- app/controllers/api/teams.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Collections.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Databases.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Executions.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Files.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Functions.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Teams.php | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Users.php | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 4f321e2818..8d5fe517d4 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1376,7 +1376,7 @@ App::get('/v1/account/logs') $grouped = Query::groupByType($queries); $limit = $grouped['limit'] ?? 25; $offset = $grouped['offset'] ?? 0; - + $audit = new EventAudit($dbForProject); $logs = $audit->getLogsByUser($user->getId(), $limit, $offset); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 415a575b6a..6900e3fec6 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -343,7 +343,7 @@ App::get('/v1/databases/:databaseId/logs') $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId; $logs = $audit->getLogsByResource($resource, $limit, $offset); - + $output = []; foreach ($logs as $i => &$log) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 1e472815fc..c5adc47148 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -162,7 +162,7 @@ App::get('/v1/storage/buckets') ->inject('dbForProject') ->inject('usage') ->action(function (array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { - + $queries = Query::parseQueries($queries); if (!empty($search)) { diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 1c53152eeb..af51e9f2da 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -877,7 +877,7 @@ App::get('/v1/teams/:teamId/logs') $grouped = Query::groupByType($queries); $limit = $grouped['limit'] ?? 25; $offset = $grouped['offset'] ?? 0; - + $audit = new Audit($dbForProject); $resource = 'team/' . $team->getId(); $logs = $audit->getLogsByResource($resource, $limit, $offset); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index e14b74ea3d..af7f7d4380 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -10,7 +10,7 @@ class Buckets extends Collection '$id', '$createdAt', '$updatedAt', - + 'enabled', 'name', 'fileSecurity', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php index b429a1b744..ea1a4ef548 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php @@ -10,7 +10,7 @@ class Collections extends Collection '$id', '$createdAt', '$updatedAt', - + 'name', 'enabled', 'documentSecurity' diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php index 8fee0492eb..aa6af85c1a 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php @@ -10,7 +10,7 @@ class Databases extends Collection '$id', '$createdAt', '$updatedAt', - + 'name' ]; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index 2d4e2ca32d..dec54311c3 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -10,7 +10,7 @@ class Deployments extends Collection '$id', '$createdAt', '$updatedAt', - + 'entrypoint', 'size', 'buildId', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php index b53fda8f18..2da974942f 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php @@ -10,7 +10,7 @@ class Executions extends Collection '$id', '$createdAt', '$updatedAt', - + 'trigger', 'status', 'statusCode', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php index 1fb9b39c5a..d66ec04a33 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php @@ -10,7 +10,7 @@ class Files extends Collection '$id', '$createdAt', '$updatedAt', - + 'name', 'signature', 'mimeType', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php index 8a08a8371a..ae3e4086c9 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php @@ -10,7 +10,7 @@ class Functions extends Collection '$id', '$createdAt', '$updatedAt', - + 'name', 'status', 'runtime', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php index 7aae93f65a..7924d2784c 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php @@ -10,7 +10,7 @@ class Teams extends Collection '$id', '$createdAt', '$updatedAt', - + 'name', 'total' ]; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php index 76321394c1..e8f2507cda 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php @@ -10,7 +10,7 @@ class Users extends Collection '$id', '$createdAt', '$updatedAt', - + 'name', 'email', 'phone', From 531d57feffc9a6a1577c12c5284ee430784b5f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 13:16:46 +0000 Subject: [PATCH 38/75] Upgrade listMemberships queries --- app/controllers/api/teams.php | 39 +++++++++++-------- .../Validator/Queries/TeamMemberships.php | 33 ++++++++++++++++ 2 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index af51e9f2da..022caf641a 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -11,6 +11,7 @@ use Appwrite\Network\Validator\Host; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries; +use Appwrite\Utopia\Database\Validator\Queries\TeamMemberships; use Appwrite\Utopia\Database\Validator\Queries\Teams; use Appwrite\Utopia\Database\Validator\Query\Limit; use Appwrite\Utopia\Database\Validator\Query\Offset; @@ -465,15 +466,11 @@ App::get('/v1/teams/:teamId/memberships') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) ->param('teamId', '', new UID(), 'Team ID.') + ->param('queries', [], new TeamMemberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', TeamMemberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of memberships to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the membership used as the starting point for the query, excluding the membership itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderType', Database::ORDER_ASC, new WhiteList([Database::ORDER_ASC, Database::ORDER_DESC], true), 'Order result by ' . Database::ORDER_ASC . ' or ' . Database::ORDER_DESC . ' order.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $teamId, string $search, int $limit, int $offset, string $cursor, string $cursorDirection, string $orderType, Response $response, Database $dbForProject) { + ->action(function (string $teamId, array $queries, string $search, Response $response, Database $dbForProject) { $team = $dbForProject->getDocument('teams', $teamId); @@ -481,29 +478,37 @@ App::get('/v1/teams/:teamId/memberships') throw new Exception(Exception::TEAM_NOT_FOUND); } - $filterQueries = [Query::equal('teamId', [$teamId])]; + $queries = Query::parseQueries($queries); if (!empty($search)) { - $filterQueries[] = Query::search('search', $search); + $queries[] = Query::search('search', $search); } - $otherQueries = []; - $otherQueries[] = Query::limit($limit); - $otherQueries[] = Query::offset($offset); - $otherQueries[] = $orderType === Database::ORDER_ASC ? Query::orderAsc('') : Query::orderDesc(''); - if (!empty($cursor)) { - $cursorDocument = $dbForProject->getDocument('memberships', $cursor); + // Set default limit + $queries[] = Query::limit(25); + + // Set internal queries + $queries[] = Query::equal('teamId', [$teamId]); + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $membershipId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('memberships', $membershipId); if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Membership '{$cursor}' for the 'cursor' value not found."); + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Membership '{$membershipId}' for the 'cursor' value not found."); } - $otherQueries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + $cursor->setValue($cursorDocument); } + $filterQueries = Query::groupByType($queries)['filters']; + $memberships = $dbForProject->find( collection: 'memberships', - queries: \array_merge($filterQueries, $otherQueries), + queries: $queries, ); $total = $dbForProject->count( diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php new file mode 100644 index 0000000000..08acba40e8 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php @@ -0,0 +1,33 @@ + Date: Tue, 23 Aug 2022 15:01:57 +0000 Subject: [PATCH 39/75] PR review changes --- composer.lock | 2 +- .../Validator/Queries/{Collection.php => Base.php} | 6 +++--- .../Utopia/Database/Validator/Queries/Buckets.php | 8 ++------ .../Database/Validator/Queries/Collections.php | 8 ++------ .../Utopia/Database/Validator/Queries/Databases.php | 8 ++------ .../Database/Validator/Queries/Deployments.php | 8 ++------ .../Utopia/Database/Validator/Queries/Executions.php | 8 ++------ .../Utopia/Database/Validator/Queries/Files.php | 8 ++------ .../Utopia/Database/Validator/Queries/Functions.php | 8 ++------ .../Database/Validator/Queries/TeamMemberships.php | 12 ++---------- .../Utopia/Database/Validator/Queries/Teams.php | 8 ++------ .../Utopia/Database/Validator/Queries/Users.php | 8 ++------ .../Database/Validator/Queries/CollectionTest.php | 8 ++++---- 13 files changed, 28 insertions(+), 72 deletions(-) rename src/Appwrite/Utopia/Database/Validator/Queries/{Collection.php => Base.php} (95%) diff --git a/composer.lock b/composer.lock index b9176fe53e..f31e5efe52 100644 --- a/composer.lock +++ b/composer.lock @@ -2874,7 +2874,7 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/master" + "source": "https://github.com/appwrite/sdk-generator/tree/feat-change-default-functionID" }, "time": "2022-08-19T10:03:22+00:00" }, diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collection.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php similarity index 95% rename from src/Appwrite/Utopia/Database/Validator/Queries/Collection.php rename to src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 0c29ecd2ff..42c60dbec4 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collection.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -12,7 +12,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -class Collection extends IndexedQueries +class Base extends IndexedQueries { /** * Expression constructor @@ -49,12 +49,12 @@ class Collection extends IndexedQueries 'array' => false, ]); $attributes[] = new Document([ - '$id' => '$createdAt', + 'key' => '$createdAt', 'type' => Database::VAR_DATETIME, 'array' => false, ]); $attributes[] = new Document([ - '$id' => '$updatedAt', + 'key' => '$updatedAt', 'type' => Database::VAR_DATETIME, 'array' => false, ]); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index af7f7d4380..b52c0456a4 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Buckets extends Collection +class Buckets extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'enabled', 'name', 'fileSecurity', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php index ea1a4ef548..579e80ceab 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Collections.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Collections extends Collection +class Collections extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'name', 'enabled', 'documentSecurity' diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php index aa6af85c1a..3278b140bf 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Databases.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Databases extends Collection +class Databases extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'name' ]; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index dec54311c3..b33a6ac5a4 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Deployments extends Collection +class Deployments extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'entrypoint', 'size', 'buildId', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php index 2da974942f..ae26b26337 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Executions.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Executions extends Collection +class Executions extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'trigger', 'status', 'statusCode', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php index d66ec04a33..8c2cf653b8 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Files.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Files.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Files extends Collection +class Files extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'name', 'signature', 'mimeType', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php index ae3e4086c9..6ecf76d7ab 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Functions extends Collection +class Functions extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'name', 'status', 'runtime', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php index 08acba40e8..eff5016e6c 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php @@ -2,21 +2,13 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class TeamMemberships extends Collection +class TeamMemberships extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'userId', - 'userName', - 'userName', - 'userEmail', 'teamId', - 'teamName', 'invited', 'joined', 'confirm' diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php index 7924d2784c..e51c565190 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Teams.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Teams extends Collection +class Teams extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'name', 'total' ]; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php index e8f2507cda..a19cbfc415 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Users.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Users.php @@ -2,15 +2,11 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; -class Users extends Collection +class Users extends Base { public const ALLOWED_ATTRIBUTES = [ - '$id', - '$createdAt', - '$updatedAt', - 'name', 'email', 'phone', diff --git a/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php b/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php index 198fc2895d..a32acc4a95 100644 --- a/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php +++ b/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php @@ -2,7 +2,7 @@ namespace Tests\Unit\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Collection; +use Appwrite\Utopia\Database\Validator\Queries\Base; use PHPUnit\Framework\TestCase; class CollectionTest extends TestCase @@ -17,14 +17,14 @@ class CollectionTest extends TestCase public function testEmptyQueries(): void { - $validator = new Collection('users', []); + $validator = new Base('users', []); $this->assertEquals($validator->isValid([]), true); } public function testValid(): void { - $validator = new Collection('users', ['name', 'search']); + $validator = new Base('users', ['name', 'search']); $this->assertEquals(true, $validator->isValid(['cursorAfter("asdf")']), $validator->getDescription()); $this->assertEquals(true, $validator->isValid(['equal("name", "value")']), $validator->getDescription()); $this->assertEquals(true, $validator->isValid(['limit(10)']), $validator->getDescription()); @@ -35,7 +35,7 @@ class CollectionTest extends TestCase public function testMissingIndex(): void { - $validator = new Collection('users', ['name']); + $validator = new Base('users', ['name']); $this->assertEquals(false, $validator->isValid(['equal("dne", "value")']), $validator->getDescription()); $this->assertEquals(false, $validator->isValid(['orderAsc("dne")']), $validator->getDescription()); $this->assertEquals(false, $validator->isValid(['search("search", "value")']), $validator->getDescription()); From 7fb74027d49b102db08dc666121b60c181b88e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Aug 2022 15:18:59 +0000 Subject: [PATCH 40/75] Upgrade listDocuments queries --- app/controllers/api/databases.php | 81 +++++-------------- .../Database/Validator/Queries/Documents.php | 19 +++++ 2 files changed, 40 insertions(+), 60 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Documents.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 6900e3fec6..9bd3a41832 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -51,6 +51,7 @@ use Appwrite\Stats\Stats; use Appwrite\Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; +use Appwrite\Utopia\Database\Validator\Queries\Documents; use Utopia\Config\Config; use MaxMind\Db\Reader; @@ -2011,18 +2012,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).') - ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/database#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) - ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. By default will return maximum 25 results. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' results allowed per request.', true) - ->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursor', '', new UID(), 'ID of the document used as the starting point for the query, excluding the document itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) - ->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor, can be either \'before\' or \'after\'.', true) - ->param('orderAttributes', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes used to sort results. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' order attributes are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) - ->param('orderTypes', [], new ArrayList(new WhiteList([Database::ORDER_DESC, Database::ORDER_ASC], true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' order types are allowed.', true) + ->param('queries', [], new Documents(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('response') ->inject('dbForProject') ->inject('usage') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, array $queries, int $limit, int $offset, string $cursor, string $cursorDirection, array $orderAttributes, array $orderTypes, Response $response, Database $dbForProject, Stats $usage, string $mode) { + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Stats $usage, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2045,70 +2040,36 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::USER_UNAUTHORIZED); } - if (!empty($queries)) { - $attributes = array_merge( - $collection->getAttribute('attributes', []), - [ - new Document([ - 'key' => '$id', - 'type' => Database::VAR_STRING, - 'array' => false, - ]), - new Document([ - 'key' => '$createdAt', - 'type' => Database::VAR_DATETIME, - 'array' => false, - ]), - new Document([ - 'key' => '$updatedAt', - 'type' => Database::VAR_DATETIME, - 'array' => false, - ]), - ] - ); - $validator = new IndexedQueries( - $attributes, - $collection->getAttribute('indexes', []), - new Cursor(), - new Filter($attributes), - new Limit(), - new Offset(), - new Order(), - ); - if (!$validator->isValid($queries)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - } + $queries = Query::parseQueries($queries); - $filterQueries = Query::parseQueries($queries); + // Set default limit + $queries[] = Query::limit(25); - $otherQueries = []; - $otherQueries[] = Query::limit($limit); - $otherQueries[] = Query::offset($offset); - foreach ($orderTypes as $i => $orderType) { - $otherQueries[] = $orderType === Database::ORDER_DESC ? Query::orderDesc($orderAttributes[$i] ?? '') : Query::orderAsc($orderAttributes[$i] ?? ''); - } - - if (!empty($cursor)) { + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE)[0] ?? null; + if ($cursor !== null) { + /** @var Query $cursor */ + $documentId = $cursor->getValue(); if ($documentSecurity) { - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $cursor); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); } else { - $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $cursor)); - } - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$cursor}' for the 'cursor' value not found."); + $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); } - $otherQueries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument); + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); } - $allQueries = \array_merge($filterQueries, $otherQueries); + $filterQueries = Query::groupByType($queries)['filters']; if ($documentSecurity) { - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $allQueries); + $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } else { - $documents = Authorization::skip(fn () => $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $allQueries)); + $documents = Authorization::skip(fn () => $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries)); $total = Authorization::skip(fn () => $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php b/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php new file mode 100644 index 0000000000..c487ed5a13 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php @@ -0,0 +1,19 @@ + Date: Tue, 23 Aug 2022 16:33:08 +0000 Subject: [PATCH 41/75] Fix listDocument queries validation --- app/controllers/api/databases.php | 9 ++++++- .../Database/Validator/Queries/Base.php | 5 ---- .../Database/Validator/Queries/Documents.php | 27 ++++++++++++++----- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 9bd3a41832..fa78d003f8 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2012,7 +2012,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/database#createCollection).') - ->param('queries', [], new Documents(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) + ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->inject('response') ->inject('dbForProject') ->inject('usage') @@ -2040,6 +2040,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::USER_UNAUTHORIZED); } + // Validate queries + $validator = new Documents($collection->getAttribute('attributes'), $collection->getAttribute('indexes')); + $valid = $validator->isValid($collection->getRead()); + if (!$valid) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription()); + } + $queries = Query::parseQueries($queries); // Set default limit diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 42c60dbec4..85f5c74ac7 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -67,11 +67,6 @@ class Base extends IndexedQueries 'attributes' => [$attribute] ]); } - $indexes[] = new Document([ - 'status' => 'available', - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'] - ]); $validators = [ new Limit(), diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php b/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php index c487ed5a13..430ad399e4 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php @@ -2,18 +2,33 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\Base; +use Appwrite\Utopia\Database\Validator\IndexedQueries; +use Appwrite\Utopia\Database\Validator\Query\Limit; +use Appwrite\Utopia\Database\Validator\Query\Offset; +use Appwrite\Utopia\Database\Validator\Query\Cursor; +use Appwrite\Utopia\Database\Validator\Query\Filter; +use Appwrite\Utopia\Database\Validator\Query\Order; +use Utopia\Database\Database; +use Utopia\Database\Document; -class Documents extends Base +class Documents extends IndexedQueries { - public const ALLOWED_ATTRIBUTES = []; - /** * Expression constructor * + * @param Document[] $attributes + * @param Document[] $indexes */ - public function __construct() + public function __construct(array $attributes, array $indexes) { - parent::__construct('documents', self::ALLOWED_ATTRIBUTES); + $validators = [ + new Limit(), + new Offset(), + new Cursor(), + new Filter($attributes), + new Order($attributes), + ]; + + parent::__construct($attributes, $indexes, ...$validators); } } From bd7395cb446414f131c62d96cf623ddc8173771f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 09:22:13 +0000 Subject: [PATCH 42/75] Bug fixing, upgrade tests to new syntax --- app/controllers/api/databases.php | 2 +- composer.lock | 2 +- .../Validator/Queries/TeamMemberships.php | 2 +- tests/e2e/Services/Account/AccountBase.php | 7 +++---- tests/e2e/Services/Databases/DatabasesBase.php | 8 ++++---- .../Functions/FunctionsCustomClientTest.php | 5 ++--- .../Services/Storage/StorageCustomServerTest.php | 2 +- tests/e2e/Services/Teams/TeamsBase.php | 15 ++++++--------- tests/e2e/Services/Teams/TeamsBaseClient.php | 2 +- 9 files changed, 20 insertions(+), 25 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index fa78d003f8..5b64db341e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2042,7 +2042,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') // Validate queries $validator = new Documents($collection->getAttribute('attributes'), $collection->getAttribute('indexes')); - $valid = $validator->isValid($collection->getRead()); + $valid = $validator->isValid($queries); if (!$valid) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription()); } diff --git a/composer.lock b/composer.lock index f31e5efe52..b9176fe53e 100644 --- a/composer.lock +++ b/composer.lock @@ -2874,7 +2874,7 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/feat-change-default-functionID" + "source": "https://github.com/appwrite/sdk-generator/tree/master" }, "time": "2022-08-19T10:03:22+00:00" }, diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php index eff5016e6c..5a29e3b63e 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php @@ -20,6 +20,6 @@ class TeamMemberships extends Base */ public function __construct() { - parent::__construct('teamMemberships', self::ALLOWED_ATTRIBUTES); + parent::__construct('memberships', self::ALLOWED_ATTRIBUTES); } } diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 1b287357b8..e5f20f1d80 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -390,7 +390,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'limit' => 1 + 'queries' => [ 'limit(1)' ], ]); $this->assertEquals($responseLimit['headers']['status-code'], 200); @@ -407,7 +407,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'offset' => 1 + 'queries' => [ 'offset(1)' ], ]); $this->assertEquals($responseOffset['headers']['status-code'], 200); @@ -424,8 +424,7 @@ trait AccountBase 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'limit' => 1, - 'offset' => 1 + 'queries' => [ 'limit(1)', 'offset(1)' ], ]); $this->assertEquals($responseLimitOffset['headers']['status-code'], 200); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 4df1c71760..21ddede753 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -986,10 +986,11 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], + 'queries' => [ 'orderAsc("releaseYear")' ], ]); + \var_dump($documents); + $this->assertEquals(200, $documents['headers']['status-code']); $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); @@ -1007,8 +1008,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['DESC'], + 'queries' => [ 'orderDesc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index cfc1b3e64a..b35b5cfab8 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -293,7 +293,7 @@ class FunctionsCustomClientTest extends Scope 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'cursor' => $base['body']['executions'][0]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['executions'][0]['$id'] . '")' ], ]); $this->assertCount(1, $executions['body']['executions']); @@ -304,8 +304,7 @@ class FunctionsCustomClientTest extends Scope 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ], [ - 'cursor' => $base['body']['executions'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['executions'][1]['$id'] . '")' ], ]); // Cleanup : Delete function diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 13130f1ea1..226df031bf 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -98,7 +98,7 @@ class StorageCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $response['body']['buckets'][0]['$id'], + 'queries' => [ 'cursorAfter("' . $response['body']['buckets'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 2404ca3243..7f2c4244d3 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -128,7 +128,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 2, + 'queries' => [ 'limit(2)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -140,7 +140,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'offset' => 1, + 'queries' => [ 'offset(1)' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -191,7 +191,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 2, + 'queries' => [ 'limit(2)' ], ]); $this->assertEquals(200, $teams['headers']['status-code']); @@ -203,8 +203,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 1, - 'cursor' => $teams['body']['teams'][0]['$id'] + 'queries' => [ 'limit(1)', 'cursorAfter("' . $teams['body']['teams'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -217,9 +216,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 1, - 'cursor' => $teams['body']['teams'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'limit(1)', 'cursorBefore("' . $teams['body']['teams'][1]['$id'] . '")' ], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -235,7 +232,7 @@ trait TeamsBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => 'unknown' + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals(400, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index e07e9fbb18..3a1921105b 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -209,7 +209,7 @@ trait TeamsBaseClient 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $memberships['body']['memberships'][0]['$id'] + 'queries' => [ 'cursorAfter("' . $memberships['body']['memberships'][0]['$id'] . '")' ] ]); $this->assertEquals(200, $response['headers']['status-code']); From 4645fcd0c8c85051ba4f28818430b17d4be7e7c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 10:31:47 +0000 Subject: [PATCH 43/75] Fix tests --- .../Database/Validator/Queries/Documents.php | 16 ++++++ .../e2e/Services/Databases/DatabasesBase.php | 53 ++++++------------- .../Databases/DatabasesCustomServerTest.php | 28 +++++----- .../Functions/FunctionsCustomServerTest.php | 7 ++- .../Validator/Queries/CollectionTest.php | 2 - .../Database/Validator/Queries/UsersTest.php | 1 - 6 files changed, 46 insertions(+), 61 deletions(-) diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php b/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php index 430ad399e4..fe1e85d699 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Documents.php @@ -21,6 +21,22 @@ class Documents extends IndexedQueries */ public function __construct(array $attributes, array $indexes) { + $attributes[] = new Document([ + 'key' => '$id', + 'type' => Database::VAR_STRING, + 'array' => false, + ]); + $attributes[] = new Document([ + 'key' => '$createdAt', + 'type' => Database::VAR_DATETIME, + 'array' => false, + ]); + $attributes[] = new Document([ + 'key' => '$updatedAt', + 'type' => Database::VAR_DATETIME, + 'array' => false, + ]); + $validators = [ new Limit(), new Offset(), diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 21ddede753..9a6eb10cd1 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -989,8 +989,6 @@ trait DatabasesBase 'queries' => [ 'orderAsc("releaseYear")' ], ]); - \var_dump($documents); - $this->assertEquals(200, $documents['headers']['status-code']); $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); @@ -1123,7 +1121,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['documents'][0]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['documents'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1135,7 +1133,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['documents'][2]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['documents'][2]['$id'] . '")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1148,8 +1146,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], + 'queries' => [ 'orderAsc("releaseYear")' ], ]); $this->assertEquals(200, $base['headers']['status-code']); @@ -1162,9 +1159,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], - 'cursor' => $base['body']['documents'][1]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1178,8 +1173,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['DESC'], + 'queries' => [ 'orderDesc("releaseYear")' ], ]); $this->assertEquals(200, $base['headers']['status-code']); @@ -1192,9 +1186,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['DESC'], - 'cursor' => $base['body']['documents'][1]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1208,7 +1200,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => 'unknown' + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals(400, $documents['headers']['status-code']); @@ -1240,8 +1232,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['documents'][2]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['documents'][2]['$id'] . '")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1253,8 +1244,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['documents'][0]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['documents'][0]['$id'] . '")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1267,8 +1257,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], + 'queries' => [ 'orderAsc("releaseYear")' ], ]); $this->assertEquals(200, $base['headers']['status-code']); @@ -1281,10 +1270,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], - 'cursor' => $base['body']['documents'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderAsc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1298,8 +1284,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['DESC'], + 'queries' => [ 'orderDesc("releaseYear")' ], ]); $this->assertEquals(200, $base['headers']['status-code']); @@ -1312,10 +1297,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['DESC'], - 'cursor' => $base['body']['documents'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['documents'][1]['$id'] . '")', 'orderDesc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1335,9 +1317,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 1, - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], + 'queries' => [ 'limit(1)', 'orderAsc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); @@ -1348,10 +1328,7 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 2, - 'offset' => 1, - 'orderAttributes' => ['releaseYear'], - 'orderTypes' => ['ASC'], + 'queries' => [ 'limit(2)', 'offset(1)', 'orderAsc("releaseYear")' ], ]); $this->assertEquals(200, $documents['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 40238550f7..6a2658651f 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -58,7 +58,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderType' => 'DESC' + 'queries' => [ 'orderDesc("$id")' ], ]); $this->assertEquals(2, $databases['body']['total']); @@ -77,7 +77,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['databases'][0]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['databases'][0]['$id'] . '")' ], ]); $this->assertCount(1, $databases['body']['databases']); @@ -87,7 +87,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['databases'][1]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['databases'][1]['$id'] . '")' ], ]); $this->assertCount(0, $databases['body']['databases']); @@ -105,8 +105,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['databases'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['databases'][1]['$id'] . '")' ], ]); $this->assertCount(1, $databases['body']['databases']); @@ -116,8 +115,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['databases'][0]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['databases'][0]['$id'] . '")' ], ]); $this->assertCount(0, $databases['body']['databases']); @@ -163,7 +161,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => 'unknown', + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -295,7 +293,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderType' => 'DESC' + 'queries' => [ 'orderDesc("$id")' ], ]); $this->assertEquals(2, $collections['body']['total']); @@ -314,7 +312,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['collections'][0]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['collections'][0]['$id'] . '")' ], ]); $this->assertCount(1, $collections['body']['collections']); @@ -324,7 +322,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['collections'][1]['$id'] + 'queries' => [ 'cursorAfter("' . $base['body']['collections'][1]['$id'] . '")' ], ]); $this->assertCount(0, $collections['body']['collections']); @@ -342,8 +340,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['collections'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['collections'][1]['$id'] . '")' ], ]); $this->assertCount(1, $collections['body']['collections']); @@ -353,8 +350,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $base['body']['collections'][0]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $base['body']['collections'][0]['$id'] . '")' ], ]); $this->assertCount(0, $collections['body']['collections']); @@ -400,7 +396,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => 'unknown', + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals(400, $response['headers']['status-code']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 450f65f305..32d24e2ce4 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -158,7 +158,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $functions['body']['functions'][0]['$id'] + 'queries' => [ 'cursorAfter("' . $functions['body']['functions'][0]['$id'] . '")' ], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -169,8 +169,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => $functions['body']['functions'][1]['$id'], - 'cursorDirection' => Database::CURSOR_BEFORE + 'queries' => [ 'cursorBefore("' . $functions['body']['functions'][1]['$id'] . '")' ], ]); $this->assertEquals($response['headers']['status-code'], 200); @@ -184,7 +183,7 @@ class FunctionsCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'cursor' => 'unknown', + 'queries' => [ 'cursorAfter("unknown")' ], ]); $this->assertEquals($response['headers']['status-code'], 400); diff --git a/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php b/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php index a32acc4a95..3899ce0d80 100644 --- a/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php +++ b/tests/unit/Utopia/Database/Validator/Queries/CollectionTest.php @@ -30,7 +30,6 @@ class CollectionTest extends TestCase $this->assertEquals(true, $validator->isValid(['limit(10)']), $validator->getDescription()); $this->assertEquals(true, $validator->isValid(['offset(10)']), $validator->getDescription()); $this->assertEquals(true, $validator->isValid(['orderAsc("name")']), $validator->getDescription()); - $this->assertEquals(true, $validator->isValid(['search("search", "value")']), $validator->getDescription()); } public function testMissingIndex(): void @@ -38,6 +37,5 @@ class CollectionTest extends TestCase $validator = new Base('users', ['name']); $this->assertEquals(false, $validator->isValid(['equal("dne", "value")']), $validator->getDescription()); $this->assertEquals(false, $validator->isValid(['orderAsc("dne")']), $validator->getDescription()); - $this->assertEquals(false, $validator->isValid(['search("search", "value")']), $validator->getDescription()); } } diff --git a/tests/unit/Utopia/Database/Validator/Queries/UsersTest.php b/tests/unit/Utopia/Database/Validator/Queries/UsersTest.php index 24a818c128..122d83d885 100644 --- a/tests/unit/Utopia/Database/Validator/Queries/UsersTest.php +++ b/tests/unit/Utopia/Database/Validator/Queries/UsersTest.php @@ -30,7 +30,6 @@ class UsersTest extends TestCase $this->assertEquals(true, $validator->isValid(['greaterThan("registration", "2020-10-15 06:38")']), $validator->getDescription()); $this->assertEquals(true, $validator->isValid(['equal("emailVerification", true)']), $validator->getDescription()); $this->assertEquals(true, $validator->isValid(['equal("phoneVerification", true)']), $validator->getDescription()); - $this->assertEquals(true, $validator->isValid(['search("search", "value")']), $validator->getDescription()); /** * Test for Failure From 22f05b4cf80d6f9fe27dbcce272b0bc8765b1ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 11:55:43 +0000 Subject: [PATCH 44/75] Include new tests, fix existing --- .../Functions/FunctionsCustomClientTest.php | 44 +++++++ .../Functions/FunctionsCustomServerTest.php | 110 ++++++++++++++++++ tests/e2e/Services/Storage/StorageBase.php | 36 ++++++ .../Storage/StorageCustomServerTest.php | 40 +++++++ tests/e2e/Services/Teams/TeamsBase.php | 20 ++++ tests/e2e/Services/Teams/TeamsBaseClient.php | 42 +++++++ tests/e2e/Services/Users/UsersBase.php | 7 +- 7 files changed, 295 insertions(+), 4 deletions(-) diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index b35b5cfab8..fb900ef252 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -288,6 +288,50 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('completed', $base['body']['executions'][0]['status']); $this->assertEquals('completed', $base['body']['executions'][1]['status']); + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'queries' => [ 'limit(1)' ] + ]); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertCount(1, $executions['body']['executions']); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'queries' => [ 'offset(1)' ] + ]); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertCount(1, $executions['body']['executions']); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'queries' => [ 'equal("status", ["completed"])' ] + ]); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertCount(2, $executions['body']['executions']); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'queries' => [ 'equal("status", ["failed"])' ] + ]); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertCount(0, $executions['body']['executions']); + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 32d24e2ce4..7922d5a0da 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -96,6 +96,46 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $response['body']['functions']); $this->assertEquals($response['body']['functions'][0]['name'], 'Test'); + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(0)' ] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(0, $response['body']['functions']); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(0, $response['body']['functions']); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("status", "disabled")' ] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(1, $response['body']['functions']); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("status", "enabled")' ] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(0, $response['body']['functions']); + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -411,6 +451,46 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(2, $function['body']['deployments']); $this->assertEquals($function['body']['deployments'][0]['$id'], $data['deploymentId']); + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(1)' ] + ]); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertCount(1, $function['body']['deployments']); + + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ] + ]); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertCount(1, $function['body']['deployments']); + + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("entrypoint", "index.php")' ] + ]); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertCount(2, $function['body']['deployments']); + + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("entrypoint", "index.js")' ] + ]); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertCount(0, $function['body']['deployments']); + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/deployments', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -547,6 +627,36 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $function['body']['executions']); $this->assertEquals($function['body']['executions'][0]['$id'], $data['executionId']); + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(0)' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(0, $response['body']['executions']); + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(0, $response['body']['executions']); + + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("trigger", "http")' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(1, $response['body']['executions']); + /** * Test search queries */ diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 3e695c73b1..026979db12 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -259,6 +259,42 @@ trait StorageBase $this->assertGreaterThan(0, $files['body']['total']); $this->assertGreaterThan(0, count($files['body']['files'])); + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(0)' ] + ]); + $this->assertEquals(200, $files['headers']['status-code']); + $this->assertEquals(0, count($files['body']['files'])); + + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ] + ]); + $this->assertEquals(200, $files['headers']['status-code']); + $this->assertEquals(0, count($files['body']['files'])); + + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("mimeType", "image/png")' ] + ]); + $this->assertEquals(200, $files['headers']['status-code']); + $this->assertEquals(1, count($files['body']['files'])); + + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("mimeType", "image/jpeg")' ] + ]); + $this->assertEquals(200, $files['headers']['status-code']); + $this->assertEquals(0, count($files['body']['files'])); + /** * Test for FAILURE unknown Bucket */ diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index 226df031bf..ac03f2b83c 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -94,6 +94,46 @@ class StorageCustomServerTest extends Scope $this->assertEquals($id, $response['body']['buckets'][0]['$id']); $this->assertEquals('Test Bucket', $response['body']['buckets'][0]['name']); + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(1)' ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(1, $response['body']['buckets']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(1, $response['body']['buckets']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("$id", "bucket1")' ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(1, $response['body']['buckets']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("fileSecurity", true)' ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(2, $response['body']['buckets']); + $response = $this->client->call(Client::METHOD_GET, '/storage/buckets', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 7f2c4244d3..e10a3f2514 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -148,6 +148,26 @@ trait TeamsBase $this->assertIsInt($response['body']['total']); $this->assertGreaterThan(2, $response['body']['teams']); + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'greaterThanEqual("total", 0)' ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(3, $response['body']['teams']); + + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("name", ["Arsenal", "Newcastle"])' ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(2, $response['body']['teams']); + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 3a1921105b..d3ece78765 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -34,6 +34,46 @@ trait TeamsBaseClient $membershipId = $response['body']['memberships'][0]['$id']; + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(0)' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(0, $response['body']['memberships']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(0, $response['body']['memberships']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("confirm", true)' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(1, $response['body']['memberships']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("confirm", false)' ] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertCount(0, $response['body']['memberships']); + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -217,6 +257,8 @@ trait TeamsBaseClient $this->assertNotEmpty($response['body']['memberships']); $this->assertCount(1, $response['body']['memberships']); $this->assertEquals($memberships['body']['memberships'][1]['$id'], $response['body']['memberships'][0]['$id']); + + } /** diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index f2e498366b..3ff4e65fa6 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -984,7 +984,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'limit' => 1 + 'queries' => [ 'limit(1)' ] ]); $this->assertEquals($logs['headers']['status-code'], 200); @@ -996,7 +996,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'offset' => 1 + 'queries' => [ 'offset(1)' ] ]); $this->assertEquals($logs['headers']['status-code'], 200); @@ -1007,8 +1007,7 @@ trait UsersBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'offset' => 1, - 'limit' => 1 + 'queries' => [ 'limit(1)', 'offset(1)' ] ]); $this->assertEquals($logs['headers']['status-code'], 200); From c3372e4a1f0ae46a9d21b69580c978576f86941b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 11:57:00 +0000 Subject: [PATCH 45/75] Fix linter --- tests/e2e/Services/Teams/TeamsBaseClient.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index d3ece78765..6553318bcf 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -257,8 +257,6 @@ trait TeamsBaseClient $this->assertNotEmpty($response['body']['memberships']); $this->assertCount(1, $response['body']['memberships']); $this->assertEquals($memberships['body']['memberships'][1]['$id'], $response['body']['memberships'][0]['$id']); - - } /** From 25590cc210523751a1931a84ec0f5a270caf1d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 12:43:07 +0000 Subject: [PATCH 46/75] Add list queries test for databases --- .../Databases/DatabasesCustomServerTest.php | 91 ++++++++++++++++++- tests/e2e/Services/Teams/TeamsBase.php | 12 +-- 2 files changed, 93 insertions(+), 10 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 6a2658651f..2b204da304 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -50,10 +50,56 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test1['body']['$id'], $databases['body']['databases'][0]['$id']); $this->assertEquals($test2['body']['$id'], $databases['body']['databases'][1]['$id']); + $base = array_reverse($databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(1)' ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("name", ["Test 1", "Test 2"])' ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(2, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("name", "Test 2")' ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + + $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("$id", "first")' ], + ]); + $this->assertEquals(200, $databases['headers']['status-code']); + $this->assertCount(1, $databases['body']['databases']); + /** * Test for Order */ - $base = array_reverse($databases['body']['databases']); $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -285,10 +331,51 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test1['body']['$id'], $collections['body']['collections'][0]['$id']); $this->assertEquals($test2['body']['$id'], $collections['body']['collections'][1]['$id']); + $base = array_reverse($collections['body']['collections']); + + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'limit(1)' ] + ]); + + $this->assertEquals(200, $collections['headers']['status-code']); + $this->assertCount(1, $collections['body']['collections']); + + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'offset(1)' ] + ]); + + $this->assertEquals(200, $collections['headers']['status-code']); + $this->assertCount(1, $collections['body']['collections']); + + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("enabled", true)' ] + ]); + + $this->assertEquals(200, $collections['headers']['status-code']); + $this->assertCount(2, $collections['body']['collections']); + + $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ 'equal("enabled", false)' ] + ]); + + $this->assertEquals(200, $collections['headers']['status-code']); + $this->assertCount(0, $collections['body']['collections']); + /** * Test for Order */ - $base = array_reverse($collections['body']['collections']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index e10a3f2514..380fb8cac5 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -132,9 +132,7 @@ trait TeamsBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertGreaterThan(0, $response['body']['total']); - $this->assertIsInt($response['body']['total']); - $this->assertCount(2, $response['body']['teams']); + $this->assertEquals(2, count($response['body']['teams'])); $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', @@ -144,9 +142,7 @@ trait TeamsBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertGreaterThan(0, $response['body']['total']); - $this->assertIsInt($response['body']['total']); - $this->assertGreaterThan(2, $response['body']['teams']); + $this->assertGreaterThan(1, count($response['body']['teams'])); $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', @@ -156,7 +152,7 @@ trait TeamsBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertCount(3, $response['body']['teams']); + $this->assertGreaterThan(2, count($response['body']['teams'])); $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', @@ -166,7 +162,7 @@ trait TeamsBase ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertCount(2, $response['body']['teams']); + $this->assertEquals(2, count($response['body']['teams'])); $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', From 55a2e5276472303e0649b6f7f3802793fe283b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 18:23:34 +0000 Subject: [PATCH 47/75] Allow unindexed internal queries --- .../Utopia/Database/Validator/Queries/Base.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 85f5c74ac7..89c82c8e82 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -2,7 +2,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\IndexedQueries; +use Appwrite\Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Query\Limit; use Appwrite\Utopia\Database\Validator\Query\Offset; use Appwrite\Utopia\Database\Validator\Query\Cursor; @@ -12,7 +12,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -class Base extends IndexedQueries +class Base extends Queries { /** * Expression constructor @@ -59,15 +59,6 @@ class Base extends IndexedQueries 'array' => false, ]); - $indexes = []; - foreach ($allowedAttributes as $attribute) { - $indexes[] = new Document([ - 'status' => 'available', - 'type' => Database::INDEX_KEY, - 'attributes' => [$attribute] - ]); - } - $validators = [ new Limit(), new Offset(), @@ -76,6 +67,6 @@ class Base extends IndexedQueries new Order($attributes), ]; - parent::__construct($attributes, $indexes, ...$validators); + parent::__construct(...$validators); } } From 65d09705acb0fffa6fe9499cafbc98a480c56ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 18:25:15 +0000 Subject: [PATCH 48/75] Simplify class name --- app/controllers/api/teams.php | 4 ++-- .../Queries/{TeamMemberships.php => Memberships.php} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/Appwrite/Utopia/Database/Validator/Queries/{TeamMemberships.php => Memberships.php} (92%) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 022caf641a..47b8c1b0cb 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -11,7 +11,7 @@ use Appwrite\Network\Validator\Host; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries; -use Appwrite\Utopia\Database\Validator\Queries\TeamMemberships; +use Appwrite\Utopia\Database\Validator\Queries\Memberships; use Appwrite\Utopia\Database\Validator\Queries\Teams; use Appwrite\Utopia\Database\Validator\Query\Limit; use Appwrite\Utopia\Database\Validator\Query\Offset; @@ -466,7 +466,7 @@ App::get('/v1/teams/:teamId/memberships') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) ->param('teamId', '', new UID(), 'Team ID.') - ->param('queries', [], new TeamMemberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', TeamMemberships::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php similarity index 92% rename from src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php rename to src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php index 5a29e3b63e..2d90eeb0e6 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/TeamMemberships.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; use Appwrite\Utopia\Database\Validator\Queries\Base; -class TeamMemberships extends Base +class Memberships extends Base { public const ALLOWED_ATTRIBUTES = [ 'userId', From b1dfd94d4933f37379413ce3ba4bdc4d138044c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 18:41:26 +0000 Subject: [PATCH 49/75] Add indexes for internal queries --- app/config/collections.php | 275 +++++++++++++++++- .../Database/Validator/Queries/Buckets.php | 2 +- .../Validator/Queries/Deployments.php | 1 - 3 files changed, 275 insertions(+), 3 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 6f284000ac..6ad859a136 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -52,6 +52,13 @@ $collections = [ 'lengths' => [], 'orders' => [], ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], ], ], 'collections' => [ @@ -150,6 +157,27 @@ $collections = [ 'lengths' => [], 'orders' => [], ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_documentSecurity'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['documentSecurity'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -1792,6 +1820,20 @@ $collections = [ 'lengths' => [], 'orders' => [], ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_total'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['total'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -1940,6 +1982,41 @@ $collections = [ 'lengths' => [], 'orders' => [], ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_teamId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_invited'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['invited'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_joined'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['joined'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_confirm'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['confirm'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -2088,7 +2165,63 @@ $collections = [ 'attributes' => ['search'], 'lengths' => [2048], 'orders' => [Database::ORDER_ASC], - ] + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_runtime'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['runtime'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_deployment'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deployment'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_schedule'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['schedule'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_scheduleNext'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['scheduleNext'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_schedulePrevious'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['schedulePrevious'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_timeout'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['timeout'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -2241,6 +2374,34 @@ $collections = [ 'lengths' => [], 'orders' => [], ], + [ + '$id' => ID::custom('_key_entrypoint'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['entrypoint'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_size'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['size'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_buildId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['buildId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_activate'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['activate'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -2513,6 +2674,34 @@ $collections = [ 'lengths' => [], 'orders' => [], ], + [ + '$id' => ID::custom('_key_trigger'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['trigger'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_statusCode'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['statusCode'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['time'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -2704,6 +2893,48 @@ $collections = [ 'lengths' => [2048], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_fileSecurity'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['fileSecurity'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_maximumFileSize'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['maximumFileSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_encryption'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['encryption'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_antivirus'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['antivirus'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ] ], @@ -3106,6 +3337,48 @@ $collections = [ 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_signature'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['signature'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_mimeType'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['mimeType'], + 'lengths' => [127], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_sizeOriginal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['sizeOriginal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksTotal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksTotal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksUploaded'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksUploaded'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], ] ], ]; diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index b52c0456a4..b4d804ec2a 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -23,4 +23,4 @@ class Buckets extends Base { parent::__construct('buckets', self::ALLOWED_ATTRIBUTES); } -} +} \ No newline at end of file diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index b33a6ac5a4..a8323a8316 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -11,7 +11,6 @@ class Deployments extends Base 'size', 'buildId', 'activate', - 'status', ]; /** From 756d0bbd5b019a4500a86fdc199a2336f4914fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Aug 2022 18:59:34 +0000 Subject: [PATCH 50/75] Linter fix --- composer.lock | 2 +- src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index b9176fe53e..2dcac966fe 100644 --- a/composer.lock +++ b/composer.lock @@ -5383,5 +5383,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php index b4d804ec2a..b52c0456a4 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Buckets.php @@ -23,4 +23,4 @@ class Buckets extends Base { parent::__construct('buckets', self::ALLOWED_ATTRIBUTES); } -} \ No newline at end of file +} From 035e72edf7467a223a3b09cd8ce0ef5d07994b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 25 Aug 2022 09:34:59 +0000 Subject: [PATCH 51/75] Lockfile update --- composer.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 0da13d2de3..39ac8e206c 100644 --- a/composer.lock +++ b/composer.lock @@ -2056,12 +2056,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "44dda6914c7be148eb59ce11847386ce39f7b106" + "reference": "336df0d08d8bd875acd6b2b87d7b24133aa016f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/44dda6914c7be148eb59ce11847386ce39f7b106", - "reference": "44dda6914c7be148eb59ce11847386ce39f7b106", + "url": "https://api.github.com/repos/utopia-php/database/zipball/336df0d08d8bd875acd6b2b87d7b24133aa016f5", + "reference": "336df0d08d8bd875acd6b2b87d7b24133aa016f5", "shasum": "" }, "require": { @@ -2112,7 +2112,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/refactor-permissions" }, - "time": "2022-08-24T10:22:04+00:00" + "time": "2022-08-25T08:19:47+00:00" }, { "name": "utopia-php/domains", @@ -5390,5 +5390,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } From c85363f355780c5309c2bcc81bca1ca42f53f7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 25 Aug 2022 09:59:28 +0000 Subject: [PATCH 52/75] Fix bugs after merge --- app/controllers/api/account.php | 3 +-- app/controllers/api/databases.php | 19 +++++-------------- app/controllers/api/storage.php | 7 ++----- app/controllers/api/users.php | 8 ++------ .../Databases/DatabasesCustomServerTest.php | 4 ++-- 5 files changed, 12 insertions(+), 29 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 1d93d8de55..e9f280eaef 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1354,8 +1354,7 @@ App::get('/v1/account/logs') ->inject('locale') ->inject('geodb') ->inject('dbForProject') - ->inject('usage') - ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject, Stats $usage) { + ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { $queries = Query::parseQueries($queries); $grouped = Query::groupByType($queries); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 884807fcfc..8ed75d88c0 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -242,8 +242,7 @@ App::get('/v1/databases') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { $queries = Query::parseQueries($queries); @@ -270,8 +269,6 @@ App::get('/v1/databases') $filterQueries = Query::groupByType($queries)['filters']; - $usage->setParam('databases.read', 1); - $response->dynamic(new Document([ 'databases' => $dbForProject->find('databases', $queries), 'total' => $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT), @@ -562,8 +559,7 @@ App::get('/v1/databases/:databaseId/collections') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (string $databaseId, array $queries, string $search, Response $response, Database $dbForProject) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -596,10 +592,6 @@ App::get('/v1/databases/:databaseId/collections') $filterQueries = Query::groupByType($queries)['filters']; - $usage - ->setParam('databaseId', $databaseId) - ->setParam('databases.collections.read', 1); - $response->dynamic(new Document([ 'collections' => $dbForProject->find('database_' . $database->getInternalId(), $queries), 'total' => $dbForProject->count('database_' . $database->getInternalId(), $filterQueries, APP_LIMIT_COUNT), @@ -1302,9 +1294,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti ->inject('response') ->inject('dbForProject') ->inject('database') - ->inject('usage') ->inject('events') - ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Stats $usage, Event $events) { + ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?bool $default, bool $array, Response $response, Database $dbForProject, EventDatabase $database, Event $events) { $attribute = createAttribute($databaseId, $collectionId, new Document([ 'key' => $key, @@ -1314,7 +1305,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti 'default' => $default, 'array' => $array, 'filters' => ['datetime'] - ]), $response, $dbForProject, $database, $events, $usage); + ]), $response, $dbForProject, $database, $events); $response->setStatusCode(Response::STATUS_CODE_ACCEPTED); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_DATETIME); @@ -1962,7 +1953,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('response') ->inject('dbForProject') ->inject('mode') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Stats $usage, string $mode) { + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 2ff83bf269..2a77e9aef7 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -155,8 +155,7 @@ App::get('/v1/storage/buckets') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { $queries = Query::parseQueries($queries); @@ -183,8 +182,6 @@ App::get('/v1/storage/buckets') $filterQueries = Query::groupByType($queries)['filters']; - $usage->setParam('storage.buckets.read', 1); - $response->dynamic(new Document([ 'buckets' => $dbForProject->find('buckets', $queries), 'total' => $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT), @@ -655,7 +652,7 @@ App::get('/v1/storage/buckets/:bucketId/files') ->inject('response') ->inject('dbForProject') ->inject('mode') - ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, Stats $usage, string $mode) { + ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 6d7529ce7e..54ca96cb13 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -347,8 +347,7 @@ App::get('/v1/users') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->inject('usage') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject, Stats $usage) { + ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { $queries = Query::parseQueries($queries); @@ -375,8 +374,6 @@ App::get('/v1/users') $filterQueries = Query::groupByType($queries)['filters']; - $usage->setParam('users.read', 1); - $response->dynamic(new Document([ 'users' => $dbForProject->find('users', $queries), 'total' => $dbForProject->count('users', $filterQueries, APP_LIMIT_COUNT), @@ -537,8 +534,7 @@ App::get('/v1/users/:userId/logs') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->inject('usage') - ->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb, Stats $usage) { + ->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $user = $dbForProject->getDocument('users', $userId); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 2b204da304..bd4e8aa77b 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -104,7 +104,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'orderDesc("$id")' ], + 'queries' => [ 'orderDesc("")' ], ]); $this->assertEquals(2, $databases['body']['total']); @@ -380,7 +380,7 @@ class DatabasesCustomServerTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'queries' => [ 'orderDesc("$id")' ], + 'queries' => [ 'orderDesc("")' ], ]); $this->assertEquals(2, $collections['body']['total']); From 8cacf91e0995ea7c8f357fa07310cf97da6c07f4 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Sat, 27 Aug 2022 20:07:55 +0000 Subject: [PATCH 53/75] feat: fix stats test namespace --- composer.lock | 12 ++++++------ tests/unit/Usage/StatsTest.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index 2d769c72e8..16da46213d 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": "1145ff29befcc4aa21b5002da0b8319c", + "content-hash": "039de21eff3a27955696a9f6f645c548", "packages": [ { "name": "adhocore/jwt", @@ -2833,12 +2833,12 @@ "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "1a67d9dcd2884a6a708176955f83e319ac53059e" + "reference": "532d4d15ec8f11539972f2848c2e230c49b24f65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1a67d9dcd2884a6a708176955f83e319ac53059e", - "reference": "1a67d9dcd2884a6a708176955f83e319ac53059e", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/532d4d15ec8f11539972f2848c2e230c49b24f65", + "reference": "532d4d15ec8f11539972f2848c2e230c49b24f65", "shasum": "" }, "require": { @@ -2875,7 +2875,7 @@ "issues": "https://github.com/appwrite/sdk-generator/issues", "source": "https://github.com/appwrite/sdk-generator/tree/feat-new-headers" }, - "time": "2022-08-19T10:03:22+00:00" + "time": "2022-08-20T07:42:55+00:00" }, { "name": "doctrine/instantiator", @@ -5375,5 +5375,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/tests/unit/Usage/StatsTest.php b/tests/unit/Usage/StatsTest.php index 29db96754f..0b39dfdaa3 100644 --- a/tests/unit/Usage/StatsTest.php +++ b/tests/unit/Usage/StatsTest.php @@ -1,6 +1,6 @@ Date: Mon, 29 Aug 2022 15:12:20 +1200 Subject: [PATCH 54/75] Fix resetting permissions after file create --- app/views/console/comps/permissions-matrix.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/console/comps/permissions-matrix.phtml b/app/views/console/comps/permissions-matrix.phtml index 09005bbb28..9976dd1de0 100644 --- a/app/views/console/comps/permissions-matrix.phtml +++ b/app/views/console/comps/permissions-matrix.phtml @@ -34,7 +34,7 @@ $escapedPermissions = \array_map(function ($perm) { data-name="" - @reset.window="permissions = rawPermissions = []"> + @reset.window="permissions.length = rawPermissions.length = 0"> Date: Mon, 29 Aug 2022 15:17:34 +1200 Subject: [PATCH 55/75] Ensure add row events are local component only --- app/views/console/comps/permissions-matrix.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/console/comps/permissions-matrix.phtml b/app/views/console/comps/permissions-matrix.phtml index 9976dd1de0..e5f23b73a3 100644 --- a/app/views/console/comps/permissions-matrix.phtml +++ b/app/views/console/comps/permissions-matrix.phtml @@ -79,7 +79,7 @@ $escapedPermissions = \array_map(function ($perm) { + @addrow.window="addPermission('',role,{})">