From 01d0ce698825c16a233a1c3944763a0de650973d Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 5 Aug 2021 21:01:00 +0200 Subject: [PATCH 01/21] feat(database): after pagination --- app/controllers/api/database.php | 14 ++- composer.json | 2 +- composer.lock | 30 +++-- tests/e2e/Services/Database/DatabaseBase.php | 109 +++++++++++++++++++ tests/e2e/Services/Storage/StorageBase.php | 4 +- 5 files changed, 143 insertions(+), 16 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 649c34645..00d86b700 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -1056,12 +1056,12 @@ App::get('/v1/database/collections/:collectionId/documents') ->param('queries', [], new ArrayList(new Text(128)), 'Array of query strings.', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true) - // TODO@kodumbeats 'after' param for pagination ->param('orderAttributes', [], new ArrayList(new Text(128)), 'Array of attributes used to sort results.', true) ->param('orderTypes', [], new ArrayList(new WhiteList(['DESC', 'ASC'], true)), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order.', true) + ->param('orderAfter', '', new UID(), 'ID of the document used to return documents listed after. Should be used for efficient pagination working with many documents.', true) ->inject('response') ->inject('dbForExternal') - ->action(function ($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $response, $dbForExternal) { + ->action(function ($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $orderAfter, $response, $dbForExternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForExternal */ @@ -1087,7 +1087,15 @@ App::get('/v1/database/collections/:collectionId/documents') throw new Exception($validator->getDescription(), 400); } - $documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes); + if (!empty($orderAfter)) { + $orderAfterDocument = $dbForExternal->getDocument($collectionId, $orderAfter); + + if ($orderAfterDocument->isEmpty()) { + throw new Exception('Document for orderAfter not found', 400); + } + } + + $documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $orderAfterDocument ?? null); $response->dynamic(new Document([ 'sum' => \count($documents), diff --git a/composer.json b/composer.json index f595bfd1a..47cfe2d00 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.6.*", + "utopia-php/database": "dev-main as 0.6.0", "utopia-php/locale": "0.3.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index b43adc916..a1bd64bb8 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": "f9727be2725e573a92b2d1aeeb77b421", + "content-hash": "1669de851a29702eba426a09a6871921", "packages": [ { "name": "adhocore/jwt", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "0.6.0", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "561adc215fce3bd3b8c3ebb971ca354fb1526f26" + "reference": "c48b60884f63a547520ecef35714827af1870bc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/561adc215fce3bd3b8c3ebb971ca354fb1526f26", - "reference": "561adc215fce3bd3b8c3ebb971ca354fb1526f26", + "url": "https://api.github.com/repos/utopia-php/database/zipball/c48b60884f63a547520ecef35714827af1870bc4", + "reference": "c48b60884f63a547520ecef35714827af1870bc4", "shasum": "" }, "require": { @@ -2011,6 +2011,7 @@ "utopia-php/cli": "^0.11.0", "vimeo/psalm": "4.0.1" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2041,9 +2042,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.6.0" + "source": "https://github.com/utopia-php/database/tree/main" }, - "time": "2021-08-03T15:13:48+00:00" + "time": "2021-08-04T16:53:44+00:00" }, { "name": "utopia-php/domains", @@ -6254,9 +6255,18 @@ "time": "2015-12-17T08:42:14+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-main", + "alias": "0.6.0", + "alias_normalized": "0.6.0.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -6278,5 +6288,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } diff --git a/tests/e2e/Services/Database/DatabaseBase.php b/tests/e2e/Services/Database/DatabaseBase.php index 755321ed7..cae46e3ff 100644 --- a/tests/e2e/Services/Database/DatabaseBase.php +++ b/tests/e2e/Services/Database/DatabaseBase.php @@ -289,6 +289,115 @@ trait DatabaseBase return []; } + /** + * @depends testCreateDocument + */ + public function testListDocumentsAfterPagination(array $data):array + { + /** + * Test after without order. + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Captain America', $base['body']['documents'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['documents'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); + $this->assertCount(3, $base['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAfter' => $base['body']['documents'][0]['$id'] + ]); + + $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][1]['$id']); + $this->assertCount(2, $documents['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAfter' => $base['body']['documents'][2]['$id'] + ]); + + $this->assertEmpty($documents['body']['documents']); + + /** + * Test with ASC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['ASC'], + ]); + + $this->assertEquals(1944, $base['body']['documents'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['ASC'], + 'orderAfter' => $base['body']['documents'][1]['$id'] + ]); + + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); + + /** + * Test with DESC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['DESC'], + ]); + + $this->assertEquals(1944, $base['body']['documents'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['DESC'], + 'orderAfter' => $base['body']['documents'][1]['$id'] + ]); + + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); + + /** + * Test after with unknown document. + */ + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAfter' => 'unknown' + ]); + + $this->assertEquals($documents['headers']['status-code'], 400); + + return []; + } + /** * @depends testCreateDocument */ diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 508866b6a..6a614c02e 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -34,7 +34,7 @@ trait StorageBase */ return ['fileId' => $file['body']['$id']]; } - + /** * @depends testCreateFile */ @@ -169,7 +169,7 @@ trait StorageBase /** * Test for FAILURE */ - + return $data; } From fb1546cfccce3df14849338774e8e09b1ba86a89 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 12:34:42 +0200 Subject: [PATCH 02/21] rename orderAfter to after --- app/controllers/api/database.php | 12 ++++++------ composer.lock | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 00d86b700..283bb77e4 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -1056,12 +1056,12 @@ App::get('/v1/database/collections/:collectionId/documents') ->param('queries', [], new ArrayList(new Text(128)), 'Array of query strings.', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the document used to return documents listed after. Should be used for efficient pagination working with many documents.', true) ->param('orderAttributes', [], new ArrayList(new Text(128)), 'Array of attributes used to sort results.', true) ->param('orderTypes', [], new ArrayList(new WhiteList(['DESC', 'ASC'], true)), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order.', true) - ->param('orderAfter', '', new UID(), 'ID of the document used to return documents listed after. Should be used for efficient pagination working with many documents.', true) ->inject('response') ->inject('dbForExternal') - ->action(function ($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $orderAfter, $response, $dbForExternal) { + ->action(function ($collectionId, $queries, $limit, $offset, $after, $orderAttributes, $orderTypes, $response, $dbForExternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForExternal */ @@ -1087,15 +1087,15 @@ App::get('/v1/database/collections/:collectionId/documents') throw new Exception($validator->getDescription(), 400); } - if (!empty($orderAfter)) { - $orderAfterDocument = $dbForExternal->getDocument($collectionId, $orderAfter); + if (!empty($after)) { + $afterDocument = $dbForExternal->getDocument($collectionId, $after); - if ($orderAfterDocument->isEmpty()) { + if ($afterDocument->isEmpty()) { throw new Exception('Document for orderAfter not found', 400); } } - $documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $orderAfterDocument ?? null); + $documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $afterDocument ?? null); $response->dynamic(new Document([ 'sum' => \count($documents), diff --git a/composer.lock b/composer.lock index d67060635..a56ff1259 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": "c2bda60e7b774a0c813f52033a268c6c", + "content-hash": "7233a857d191a94d96aa5d0fa59d7bce", "packages": [ { "name": "adhocore/jwt", @@ -1988,12 +1988,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "c48b60884f63a547520ecef35714827af1870bc4" + "reference": "59d9d34164b6fb896bc43085a9a82a292b43473a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/c48b60884f63a547520ecef35714827af1870bc4", - "reference": "c48b60884f63a547520ecef35714827af1870bc4", + "url": "https://api.github.com/repos/utopia-php/database/zipball/59d9d34164b6fb896bc43085a9a82a292b43473a", + "reference": "59d9d34164b6fb896bc43085a9a82a292b43473a", "shasum": "" }, "require": { @@ -2042,9 +2042,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/main" + "source": "https://github.com/utopia-php/database/tree/0.6.1" }, - "time": "2021-08-04T16:53:44+00:00" + "time": "2021-08-05T17:19:16+00:00" }, { "name": "utopia-php/domains", From 99442bdfc399903866358518323c046f8c0fbf42 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 12:36:32 +0200 Subject: [PATCH 03/21] revert utopia-php/database from dev to tag --- composer.json | 2 +- composer.lock | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index 20f962476..b3593e34d 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-main as 0.6.0", + "utopia-php/database": "0.6.*", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index a56ff1259..9a8a5a4f1 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": "7233a857d191a94d96aa5d0fa59d7bce", + "content-hash": "c2bda60e7b774a0c813f52033a268c6c", "packages": [ { "name": "adhocore/jwt", @@ -1984,7 +1984,7 @@ }, { "name": "utopia-php/database", - "version": "dev-main", + "version": "0.6.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", @@ -2011,7 +2011,6 @@ "utopia-php/cli": "^0.11.0", "vimeo/psalm": "4.0.1" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -6255,18 +6254,9 @@ "time": "2015-12-17T08:42:14+00:00" } ], - "aliases": [ - { - "package": "utopia-php/database", - "version": "dev-main", - "alias": "0.6.0", - "alias_normalized": "0.6.0.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From dac093c645647d03ce0d7a18d31602644b0ac972 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 14:35:57 +0200 Subject: [PATCH 04/21] feat(database): add after pagination --- app/controllers/api/database.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 283bb77e4..ff1edd8a3 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -180,17 +180,26 @@ App::get('/v1/database/collections') ->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, 40000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the collection used to return collection listed after. Should be used for efficient pagination working with many collections.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForExternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForExternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForExternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForExternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; + if (!empty($after)) { + $afterCollection = $dbForExternal->getDocument('collections', $after); + + if ($afterCollection->isEmpty()) { + throw new Exception('Collection for after not found', 400); + } + } + $response->dynamic(new Document([ - 'collections' => $dbForExternal->find(Database::COLLECTIONS, $queries, $limit, $offset, ['_id'], [$orderType]), + 'collections' => $dbForExternal->find(Database::COLLECTIONS, $queries, $limit, $offset, [], [$orderType], $afterCollection ?? null), 'sum' => $dbForExternal->count(Database::COLLECTIONS, $queries, APP_LIMIT_COUNT), ]), Response::MODEL_COLLECTION_LIST); }); From a49b12c542679556000637cea3a49b354f7096dd Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 14:36:05 +0200 Subject: [PATCH 05/21] feat(functions): add after pagination --- app/controllers/api/functions.php | 45 ++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 8d2f28a87..4adfd81fe 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -85,17 +85,26 @@ App::get('/v1/functions') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the function used to return functions listed after. Should be used for efficient pagination working with many functions.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; + if (!empty($after)) { + $afterFunction = $dbForInternal->getDocument('functions', $after); + + if ($afterFunction->isEmpty()) { + throw new Exception('Function for after not found', 400); + } + } + $response->dynamic(new Document([ - 'functions' => $dbForInternal->find('functions', $queries, $limit, $offset, ['_id'], [$orderType]), + 'functions' => $dbForInternal->find('functions', $queries, $limit, $offset, [], [$orderType], $afterFunction ?? null), 'sum' => $dbForInternal->count('functions', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_FUNCTION_LIST); }); @@ -502,10 +511,11 @@ App::get('/v1/functions/:functionId/tags') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the tag used to return tags listed after. Should be used for efficient pagination working with many tags.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($functionId, $search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($functionId, $search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ @@ -516,8 +526,16 @@ App::get('/v1/functions/:functionId/tags') } $queries[] = new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]); - - $results = $dbForInternal->find('tags', $queries, $limit, $offset, ['_id'], [$orderType]); + + if (!empty($after)) { + $afterTag = $dbForInternal->getDocument('tags', $after); + + if ($afterTag->isEmpty()) { + throw new Exception('Tag for after not found', 400); + } + } + + $results = $dbForInternal->find('tags', $queries, $limit, $offset, [], [$orderType], $afterTag ?? null); $sum = $dbForInternal->count('tags', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ @@ -743,12 +761,13 @@ App::get('/v1/functions/:functionId/executions') ->param('functionId', '', new UID(), 'Function unique ID.') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the execution used to return executions listed after. Should be used for efficient pagination working with many executions.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($functionId, $limit, $offset, $response, $dbForInternal) { + ->action(function ($functionId, $limit, $offset, $after, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - + Authorization::disable(); $function = $dbForInternal->getDocument('functions', $functionId); Authorization::reset(); @@ -757,10 +776,18 @@ App::get('/v1/functions/:functionId/executions') throw new Exception('Function not found', 404); } + if (!empty($after)) { + $afterExecution = $dbForInternal->getDocument('executions', $after); + + if ($afterExecution->isEmpty()) { + throw new Exception('Execution for after not found', 400); + } + } + $results = $dbForInternal->find('executions', [ new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]), - ], $limit, $offset, ['_id'], [Database::ORDER_DESC]); - + ], $limit, $offset, [], [Database::ORDER_DESC], $afterExecution ?? null); + $sum = $dbForInternal->count('executions', [ new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]), ], APP_LIMIT_COUNT); From ca9dafddae229532d2a6d9e4aa26273e5db81ad8 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 14:36:17 +0200 Subject: [PATCH 06/21] feat(projects): add after pagination --- app/controllers/api/projects.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 44fa614ad..030ec3a76 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -166,16 +166,25 @@ App::get('/v1/projects') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the project used to return projects listed after. Should be used for efficient pagination working with many projects.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForConsole') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForConsole) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - $results = $dbForConsole->find('projects', $queries, $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterProject = $dbForConsole->getDocument('projects', $after); + + if ($afterProject->isEmpty()) { + throw new Exception('Project for after not found', 400); + } + } + + $results = $dbForConsole->find('projects', $queries, $limit, $offset, [], [$orderType], $afterProject ?? null); $sum = $dbForConsole->count('projects', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ From 8e6c415d01f88474cd1244db721c5b40ee8aa42d Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 14:36:27 +0200 Subject: [PATCH 07/21] feat(storage): add after pagination --- app/controllers/api/storage.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 552b0a9df..cf7ec10fb 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -168,17 +168,26 @@ App::get('/v1/storage/files') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the file used to return files listed after. Should be used for efficient pagination working with many files.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : []; + if (!empty($after)) { + $afterFile = $dbForInternal->getDocument('files', $after); + + if ($afterFile->isEmpty()) { + throw new Exception('File for after not found', 400); + } + } + $response->dynamic(new Document([ - 'files' => $dbForInternal->find('files', $queries, $limit, $offset, ['_id'], [$orderType]), + 'files' => $dbForInternal->find('files', $queries, $limit, $offset, [], [$orderType], $afterFile ?? null), 'sum' => $dbForInternal->count('files', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_FILE_LIST); }); From 79971330f2b739a338b2815f517509e54fa87ae1 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 14:36:35 +0200 Subject: [PATCH 08/21] feat(teams): add after pagination --- app/controllers/api/teams.php | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index b9015267a..ee08f8cae 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -97,16 +97,25 @@ App::get('/v1/teams') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the team used to return teams listed after. Should be used for efficient pagination working with many teams.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - $results = $dbForInternal->find('teams', $queries, $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterTeam = $dbForInternal->getDocument('teams', $after); + + if ($afterTeam->isEmpty()) { + throw new Exception('Team for after not found', 400); + } + } + + $results = $dbForInternal->find('teams', $queries, $limit, $offset, [], [$orderType], $afterTeam ?? null); $sum = $dbForInternal->count('teams', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ @@ -413,10 +422,11 @@ App::get('/v1/teams/:teamId/memberships') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the file used to return files listed after. Should be used for efficient pagination working with many files.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($teamId, $search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($teamId, $search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ @@ -426,7 +436,15 @@ App::get('/v1/teams/:teamId/memberships') throw new Exception('Team not found', 404); } - $memberships = $dbForInternal->find('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterMembership = $dbForInternal->getDocument('memberships', $after); + + if ($afterMembership->isEmpty()) { + throw new Exception('Membership for after not found', 400); + } + } + + $memberships = $dbForInternal->find('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], $limit, $offset, [], [$orderType], $afterMembership ?? null); $sum = $dbForInternal->count('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], APP_LIMIT_COUNT); $users = []; From af570076122eba98863d1a40814620a2bffd100e Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 6 Aug 2021 14:36:48 +0200 Subject: [PATCH 09/21] feat(users): add after pagination --- app/controllers/api/users.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 8c30b8b1c..bff1373f3 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -81,14 +81,23 @@ App::get('/v1/users') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the user used to return users listed after. Should be used for efficient pagination working with many users.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - $results = $dbForInternal->find('users', [], $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterUser = $dbForInternal->getDocument('users', $after); + + if ($afterUser->isEmpty()) { + throw new Exception('User for after not found', 400); + } + } + + $results = $dbForInternal->find('users', [], $limit, $offset, [], [$orderType], $afterUser ?? null); $sum = $dbForInternal->count('users', [], APP_LIMIT_COUNT); $response->dynamic(new Document([ From 2a540ff7999dde8c70a0473a48175d30e2d7f6d0 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 14:33:16 +0200 Subject: [PATCH 10/21] tests(functions): after paginatio tests --- composer.json | 2 +- composer.lock | 29 ++++++---- .../Functions/FunctionsCustomClientTest.php | 57 +++++++++++++++---- .../Functions/FunctionsCustomServerTest.php | 47 +++++++++++++-- 4 files changed, 106 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index b3593e34d..3bb8025ee 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.6.*", + "utopia-php/database": "dev-fix-after-pagination-with-order as 0.6.1", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index c528f3954..141427beb 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": "c2bda60e7b774a0c813f52033a268c6c", + "content-hash": "e79cbd92bfd81499b5111bf3329e2318", "packages": [ { "name": "adhocore/jwt", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "0.6.1", + "version": "dev-fix-after-pagination-with-order", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "59d9d34164b6fb896bc43085a9a82a292b43473a" + "reference": "2179adfdeb385864cebc86e2b063929dcfbf77e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/59d9d34164b6fb896bc43085a9a82a292b43473a", - "reference": "59d9d34164b6fb896bc43085a9a82a292b43473a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/2179adfdeb385864cebc86e2b063929dcfbf77e6", + "reference": "2179adfdeb385864cebc86e2b063929dcfbf77e6", "shasum": "" }, "require": { @@ -2041,9 +2041,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.6.1" + "source": "https://github.com/utopia-php/database/tree/fix-after-pagination-with-order" }, - "time": "2021-08-05T17:19:16+00:00" + "time": "2021-08-09T12:01:35+00:00" }, { "name": "utopia-php/domains", @@ -6254,9 +6254,18 @@ "time": "2015-12-17T08:42:14+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-fix-after-pagination-with-order", + "alias": "0.6.1", + "alias_normalized": "0.6.1.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -6278,5 +6287,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 1ebc65489..86f6fde48 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -112,7 +112,7 @@ class FunctionsCustomClientTest extends Scope ]); $this->assertEquals(201, $execution['headers']['status-code']); - + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -121,7 +121,7 @@ class FunctionsCustomClientTest extends Scope ]); $this->assertEquals(401, $execution['headers']['status-code']); - + return []; } @@ -187,7 +187,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $execution['headers']['status-code']); $executionId = $execution['body']['$id'] ?? ''; - + sleep(10); $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, [ @@ -212,19 +212,52 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); $this->assertNotEmpty($output['APPWRITE_FUNCTION_JWT']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + return [ + 'functionId' => $functionId + ]; + } + + /** + * @depends testCreateCustomExecution + */ + public function testListExecutions(array $data) + { + $functionId = $data['functionId']; + $projectId = $this->getProject()['$id']; + $apikey = $this->getProject()['apiKey']; + + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), [ + 'data' => 'foobar', + ]); + + $this->assertEquals(201, $execution['headers']['status-code']); + + sleep(10); + + $base = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ]); - $this->assertEquals(200, $executions['headers']['status-code']); - $this->assertCount(1, $executions['body']['executions']); - $this->assertEquals('completed', $executions['body']['executions'][0]['status']); - $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['stdout']); - $this->assertStringContainsString($this->getUser()['$id'], $executions['body']['executions'][0]['stdout']); - - return []; - } + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertCount(2, $base['body']['executions']); + $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, + ], [ + 'after' => $base['body']['executions'][0]['$id'] + ]); + + $this->assertCount(1, $executions['body']['executions']); + $this->assertEquals($base['body']['executions'][1]['$id'], $executions['body']['executions'][0]['$id']); + + } } diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index b78f9d42f..cb820b45c 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -77,16 +77,51 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + + $response = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'functionId' => 'unique()', + 'name' => 'Test 2', + 'runtime' => 'php-8.0', + 'vars' => [ + 'funcKey1' => 'funcValue1', + 'funcKey2' => 'funcValue2', + 'funcKey3' => 'funcValue3', + ], + 'events' => [ + 'account.create', + 'account.delete', + ], + 'schedule' => '0 0 1 1 *', + 'timeout' => 10, + ]); + $this->assertNotEmpty($response['body']['$id']); + + $functions = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals($function['headers']['status-code'], 200); - $this->assertEquals($function['body']['sum'], 1); - $this->assertIsArray($function['body']['functions']); - $this->assertCount(1, $function['body']['functions']); - $this->assertEquals($function['body']['functions'][0]['name'], 'Test'); + $this->assertEquals($functions['headers']['status-code'], 200); + $this->assertEquals($functions['body']['sum'], 2); + $this->assertIsArray($functions['body']['functions']); + $this->assertCount(2, $functions['body']['functions']); + $this->assertEquals($functions['body']['functions'][0]['name'], 'Test'); + $this->assertEquals($functions['body']['functions'][1]['name'], 'Test 2'); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $functions['body']['functions'][0]['$id'] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(1, $response['body']['functions']); + $this->assertEquals($response['body']['functions'][0]['name'], 'Test 2'); + return $data; } From d85997e33ec2efd3c77b504a7a5f5019a84618c8 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 14:47:16 +0200 Subject: [PATCH 11/21] tests(projects): after pagination tests --- .../Projects/ProjectsConsoleClientTest.php | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index fd5b70879..4d83efb41 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -63,7 +63,7 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(400, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -97,6 +97,60 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals($id, $response['body']['projects'][0]['$id']); $this->assertEquals('Project Test', $response['body']['projects'][0]['name']); + /** + * Test after pagination + */ + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => 'unique()', + 'name' => 'Project Test 2', + ]); + + $this->assertEquals(201, $team['headers']['status-code']); + $this->assertEquals('Project Test 2', $team['body']['name']); + $this->assertNotEmpty($team['body']['$id']); + + $response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => 'unique()', + 'name' => 'Project Test 2', + 'teamId' => $team['body']['$id'], + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals('Project Test 2', $response['body']['name']); + $this->assertEquals($team['body']['$id'], $response['body']['teamId']); + $this->assertArrayHasKey('platforms', $response['body']); + $this->assertArrayHasKey('webhooks', $response['body']); + $this->assertArrayHasKey('keys', $response['body']); + + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertCount(2, $response['body']['projects']); + $this->assertEquals('Project Test', $response['body']['projects'][0]['name']); + $this->assertEquals('Project Test 2', $response['body']['projects'][1]['name']); + + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()),[ + 'after' => $response['body']['projects'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertCount(1, $response['body']['projects']); + $this->assertEquals('Project Test 2', $response['body']['projects'][0]['name']); /** * Test for FAILURE */ From 0b3bf500748b61a4125963da3ffe01e8f0f465ba Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 14:55:30 +0200 Subject: [PATCH 12/21] tests(users): after pagination tests --- tests/e2e/Services/Users/UsersBase.php | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index e5907105e..b35f355c9 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -50,6 +50,42 @@ trait UsersBase return ['userId' => $user['body']['$id']]; } + /** + * @depends testCreateUser + */ + public function testListUsers(array $data): void + { + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(2, $response['body']['users']); + + $this->assertEquals($response['body']['users'][0]['$id'], $data['userId']); + $this->assertEquals($response['body']['users'][1]['$id'], 'user1'); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $response['body']['users'][0]['$id'] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + + $this->assertEquals($response['body']['users'][0]['$id'], 'user1'); + } + /** * @depends testCreateUser */ From 69e5194dd6f139a7d15ff5cfbb5c9579759326cf Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 15:04:14 +0200 Subject: [PATCH 13/21] tests(teams): after pagination tests --- tests/e2e/Services/Teams/TeamsBase.php | 32 ++++++++++++++++++-- tests/e2e/Services/Teams/TeamsBaseClient.php | 29 ++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 3e4a4971f..6c1ebbe36 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -133,7 +133,7 @@ trait TeamsBase $this->assertGreaterThan(0, $response['body']['sum']); $this->assertIsInt($response['body']['sum']); $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'], @@ -145,7 +145,7 @@ trait TeamsBase $this->assertGreaterThan(0, $response['body']['sum']); $this->assertIsInt($response['body']['sum']); $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'], @@ -158,7 +158,7 @@ trait TeamsBase $this->assertIsInt($response['body']['sum']); $this->assertCount(1, $response['body']['teams']); $this->assertEquals('Manchester United', $response['body']['teams'][0]['name']); - + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -172,6 +172,32 @@ trait TeamsBase $this->assertCount(1, $response['body']['teams']); $this->assertEquals('Manchester United', $response['body']['teams'][0]['name']); + $teams = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 2, + ]); + + $this->assertEquals(200, $teams['headers']['status-code']); + $this->assertGreaterThan(0, $teams['body']['sum']); + $this->assertIsInt($teams['body']['sum']); + $this->assertCount(2, $teams['body']['teams']); + + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 1, + 'after' => $teams['body']['teams'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertGreaterThan(0, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['teams']); + $this->assertEquals($teams['body']['teams'][1]['$id'], $response['body']['teams'][0]['$id']); + /** * Test for FAILURE */ diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index ad5773729..90964c4f6 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -138,6 +138,35 @@ trait TeamsBaseClient ]; } + /** + * @depends testCreateTeamMembership + */ + public function testListTeamMemberships($data): void + { + $memberships = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $memberships['headers']['status-code']); + $this->assertIsInt($memberships['body']['sum']); + $this->assertNotEmpty($memberships['body']['memberships']); + $this->assertCount(2, $memberships['body']['memberships']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $memberships['body']['memberships'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['sum']); + $this->assertNotEmpty($response['body']['memberships']); + $this->assertCount(1, $response['body']['memberships']); + $this->assertEquals($memberships['body']['memberships'][1]['$id'], $response['body']['memberships'][0]['$id']); + } + /** * @depends testCreateTeamMembership */ From ae28fcf4f97932d4fc94e816a6e1099bb6ec63ab Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 15:08:44 +0200 Subject: [PATCH 14/21] tests(storage): after pagination tests --- tests/e2e/Services/Storage/StorageBase.php | 36 ++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 329047b8a..57a5ee697 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -158,14 +158,44 @@ trait StorageBase /** * Test for SUCCESS */ + $file = $this->client->call(Client::METHOD_POST, '/storage/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => 'unique()', + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + + $this->assertEquals($file['headers']['status-code'], 201); + $this->assertNotEmpty($file['body']['$id']); + $this->assertIsInt($file['body']['dateCreated']); + $this->assertEquals('logo.png', $file['body']['name']); + $this->assertEquals('image/png', $file['body']['mimeType']); + $this->assertEquals(47218, $file['body']['sizeOriginal']); + $files = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], $this->getHeaders()), [ + 'limit' => 2 + ]); $this->assertEquals(200, $files['headers']['status-code']); - $this->assertGreaterThan(0, $files['body']['sum']); - $this->assertGreaterThan(0, count($files['body']['files'])); + $this->assertCount(2, $files['body']['files']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 1, + 'after' => $files['body']['files'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($files['body']['files'][1]['$id'], $response['body']['files'][0]['$id']); + $this->assertCount(1, $response['body']['files']); /** * Test for FAILURE From 40ecd0688aae3f79b22e9ae7c96b53a48a960286 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 15:12:09 +0200 Subject: [PATCH 15/21] chore(composer): update --- composer.json | 2 +- composer.lock | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 3bb8025ee..4a5685b4c 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-fix-after-pagination-with-order as 0.6.1", + "utopia-php/database": "dev-main as 0.6.1", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index 141427beb..35275b960 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": "e79cbd92bfd81499b5111bf3329e2318", + "content-hash": "6b3c314f3faa9c3aff868eaf7f6f3cbb", "packages": [ { "name": "adhocore/jwt", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "dev-fix-after-pagination-with-order", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "2179adfdeb385864cebc86e2b063929dcfbf77e6" + "reference": "272bb30d641792fb82f68adcd002be3bd34c5461" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/2179adfdeb385864cebc86e2b063929dcfbf77e6", - "reference": "2179adfdeb385864cebc86e2b063929dcfbf77e6", + "url": "https://api.github.com/repos/utopia-php/database/zipball/272bb30d641792fb82f68adcd002be3bd34c5461", + "reference": "272bb30d641792fb82f68adcd002be3bd34c5461", "shasum": "" }, "require": { @@ -2011,6 +2011,7 @@ "utopia-php/cli": "^0.11.0", "vimeo/psalm": "4.0.1" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2041,9 +2042,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/fix-after-pagination-with-order" + "source": "https://github.com/utopia-php/database/tree/main" }, - "time": "2021-08-09T12:01:35+00:00" + "time": "2021-08-09T13:01:43+00:00" }, { "name": "utopia-php/domains", @@ -6257,7 +6258,7 @@ "aliases": [ { "package": "utopia-php/database", - "version": "dev-fix-after-pagination-with-order", + "version": "dev-main", "alias": "0.6.1", "alias_normalized": "0.6.1.0" } From f7be5cd7b1a5b30111590cfde532766ccbe3cea7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 16:54:10 +0200 Subject: [PATCH 16/21] tests(database): after pagination tests --- tests/e2e/Services/Database/DatabaseBase.php | 10 +-- .../Database/DatabaseCustomServerTest.php | 80 +++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/tests/e2e/Services/Database/DatabaseBase.php b/tests/e2e/Services/Database/DatabaseBase.php index aa246706f..6ea9a885e 100644 --- a/tests/e2e/Services/Database/DatabaseBase.php +++ b/tests/e2e/Services/Database/DatabaseBase.php @@ -316,7 +316,7 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAfter' => $base['body']['documents'][0]['$id'] + 'after' => $base['body']['documents'][0]['$id'] ]); $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][0]['$id']); @@ -327,7 +327,7 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAfter' => $base['body']['documents'][2]['$id'] + 'after' => $base['body']['documents'][2]['$id'] ]); $this->assertEmpty($documents['body']['documents']); @@ -354,7 +354,7 @@ trait DatabaseBase ], $this->getHeaders()), [ 'orderAttributes' => ['releaseYear'], 'orderTypes' => ['ASC'], - 'orderAfter' => $base['body']['documents'][1]['$id'] + 'after' => $base['body']['documents'][1]['$id'] ]); $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); @@ -382,7 +382,7 @@ trait DatabaseBase ], $this->getHeaders()), [ 'orderAttributes' => ['releaseYear'], 'orderTypes' => ['DESC'], - 'orderAfter' => $base['body']['documents'][1]['$id'] + 'after' => $base['body']['documents'][1]['$id'] ]); $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); @@ -395,7 +395,7 @@ trait DatabaseBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'orderAfter' => 'unknown' + 'after' => 'unknown' ]); $this->assertEquals($documents['headers']['status-code'], 400); diff --git a/tests/e2e/Services/Database/DatabaseCustomServerTest.php b/tests/e2e/Services/Database/DatabaseCustomServerTest.php index dea3b588c..68cc4ee44 100644 --- a/tests/e2e/Services/Database/DatabaseCustomServerTest.php +++ b/tests/e2e/Services/Database/DatabaseCustomServerTest.php @@ -13,6 +13,86 @@ class DatabaseCustomServerTest extends Scope use ProjectCustom; use SideServer; + public function testListCollections() + { + /** + * Test for SUCCESS + */ + $test1 = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 1', + 'collectionId' => 'first', + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + + $test2 = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 2', + 'collectionId' => 'second', + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(2, $collections['body']['sum']); + $this->assertEquals($test1['body']['$id'], $collections['body']['collections'][0]['$id']); + $this->assertEquals($test2['body']['$id'], $collections['body']['collections'][1]['$id']); + + /** + * Test for Order + */ + $base = array_reverse($collections['body']['collections']); + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderType' => 'DESC' + ]); + + $this->assertEquals(2, $collections['body']['sum']); + $this->assertEquals($base[0]['$id'], $collections['body']['collections'][0]['$id']); + $this->assertEquals($base[1]['$id'], $collections['body']['collections'][1]['$id']); + + /** + * Test for After + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $base['body']['collections'][0]['$id'] + ]); + + $this->assertCount(1, $collections['body']['collections']); + $this->assertEquals($base['body']['collections'][1]['$id'], $collections['body']['collections'][0]['$id']); + + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $base['body']['collections'][1]['$id'] + ]); + + $this->assertCount(0, $collections['body']['collections']); + $this->assertEmpty($collections['body']['collections']); + } + public function testDeleteCollection() { /** From 26c27ff876196e9398d33c5fa5fc437cecc7dfce Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 16:54:27 +0200 Subject: [PATCH 17/21] add temporary dependency from branch --- composer.json | 2 +- composer.lock | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 4a5685b4c..567f4a4fb 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-main as 0.6.1", + "utopia-php/database": "dev-fix-update-document-cache as 0.6.1", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index 35275b960..4c8eab6db 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": "6b3c314f3faa9c3aff868eaf7f6f3cbb", + "content-hash": "e2cbe858dd5e1a6575d4631e2886e1e3", "packages": [ { "name": "adhocore/jwt", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "dev-main", + "version": "dev-fix-update-document-cache", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "272bb30d641792fb82f68adcd002be3bd34c5461" + "reference": "13cafc216c53e22cedadc42aa9e4c9297f07c4de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/272bb30d641792fb82f68adcd002be3bd34c5461", - "reference": "272bb30d641792fb82f68adcd002be3bd34c5461", + "url": "https://api.github.com/repos/utopia-php/database/zipball/13cafc216c53e22cedadc42aa9e4c9297f07c4de", + "reference": "13cafc216c53e22cedadc42aa9e4c9297f07c4de", "shasum": "" }, "require": { @@ -2011,7 +2011,6 @@ "utopia-php/cli": "^0.11.0", "vimeo/psalm": "4.0.1" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2042,9 +2041,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/main" + "source": "https://github.com/utopia-php/database/tree/fix-update-document-cache" }, - "time": "2021-08-09T13:01:43+00:00" + "time": "2021-08-09T14:46:11+00:00" }, { "name": "utopia-php/domains", @@ -6258,7 +6257,7 @@ "aliases": [ { "package": "utopia-php/database", - "version": "dev-main", + "version": "dev-fix-update-document-cache", "alias": "0.6.1", "alias_normalized": "0.6.1.0" } From a2372d2bad9bcae96743d93c0216ab41ffa402a5 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 9 Aug 2021 17:56:58 +0200 Subject: [PATCH 18/21] chore(composer): update --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 4c8eab6db..1cb2819aa 100644 --- a/composer.lock +++ b/composer.lock @@ -1988,12 +1988,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "13cafc216c53e22cedadc42aa9e4c9297f07c4de" + "reference": "3672e3f5d70457ba4c46980b765c772bdf898e04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/13cafc216c53e22cedadc42aa9e4c9297f07c4de", - "reference": "13cafc216c53e22cedadc42aa9e4c9297f07c4de", + "url": "https://api.github.com/repos/utopia-php/database/zipball/3672e3f5d70457ba4c46980b765c772bdf898e04", + "reference": "3672e3f5d70457ba4c46980b765c772bdf898e04", "shasum": "" }, "require": { @@ -2043,7 +2043,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/fix-update-document-cache" }, - "time": "2021-08-09T14:46:11+00:00" + "time": "2021-08-09T15:56:38+00:00" }, { "name": "utopia-php/domains", From 7aa712ed7cb4c1c1d791b9c2b7a3fd5502913dd2 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 10 Aug 2021 10:42:45 +0200 Subject: [PATCH 19/21] chore(composer): update --- composer.json | 2 +- composer.lock | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 567f4a4fb..4a5685b4c 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-fix-update-document-cache as 0.6.1", + "utopia-php/database": "dev-main as 0.6.1", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index 1cb2819aa..844a74639 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": "e2cbe858dd5e1a6575d4631e2886e1e3", + "content-hash": "6b3c314f3faa9c3aff868eaf7f6f3cbb", "packages": [ { "name": "adhocore/jwt", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "dev-fix-update-document-cache", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "3672e3f5d70457ba4c46980b765c772bdf898e04" + "reference": "bd765cd67e042defb8d0a15ef9a400784d6beb24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/3672e3f5d70457ba4c46980b765c772bdf898e04", - "reference": "3672e3f5d70457ba4c46980b765c772bdf898e04", + "url": "https://api.github.com/repos/utopia-php/database/zipball/bd765cd67e042defb8d0a15ef9a400784d6beb24", + "reference": "bd765cd67e042defb8d0a15ef9a400784d6beb24", "shasum": "" }, "require": { @@ -2011,6 +2011,7 @@ "utopia-php/cli": "^0.11.0", "vimeo/psalm": "4.0.1" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2041,9 +2042,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/fix-update-document-cache" + "source": "https://github.com/utopia-php/database/tree/main" }, - "time": "2021-08-09T15:56:38+00:00" + "time": "2021-08-10T06:09:02+00:00" }, { "name": "utopia-php/domains", @@ -6257,7 +6258,7 @@ "aliases": [ { "package": "utopia-php/database", - "version": "dev-fix-update-document-cache", + "version": "dev-main", "alias": "0.6.1", "alias_normalized": "0.6.1.0" } From 1061dc63661d682bb071df0b79981cbf8288ad4f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 11 Aug 2021 15:30:25 +0200 Subject: [PATCH 20/21] fix(after-pagination): updated descriptions --- app/controllers/api/database.php | 8 ++++---- app/controllers/api/functions.php | 12 ++++++------ app/controllers/api/projects.php | 4 ++-- app/controllers/api/storage.php | 4 ++-- app/controllers/api/teams.php | 8 ++++---- app/controllers/api/users.php | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index d48a94468..f89f87d90 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -182,7 +182,7 @@ App::get('/v1/database/collections') ->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, 40000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the collection used to return collection listed after. Should be used for efficient pagination working with many collections.', true) + ->param('after', '', 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('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForExternal') @@ -196,7 +196,7 @@ App::get('/v1/database/collections') $afterCollection = $dbForExternal->getDocument('collections', $after); if ($afterCollection->isEmpty()) { - throw new Exception('Collection for after not found', 400); + throw new Exception("Collection '{$after}' for the 'after' value not found.", 400); } } @@ -1068,7 +1068,7 @@ App::get('/v1/database/collections/:collectionId/documents') ->param('queries', [], new ArrayList(new Text(128)), 'Array of query strings.', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the document used to return documents listed after. Should be used for efficient pagination working with many documents.', true) + ->param('after', '', 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.', true) ->param('orderAttributes', [], new ArrayList(new Text(128)), 'Array of attributes used to sort results.', true) ->param('orderTypes', [], new ArrayList(new WhiteList(['DESC', 'ASC'], true)), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order.', true) ->inject('response') @@ -1103,7 +1103,7 @@ App::get('/v1/database/collections/:collectionId/documents') $afterDocument = $dbForExternal->getDocument($collectionId, $after); if ($afterDocument->isEmpty()) { - throw new Exception('Document for orderAfter not found', 400); + throw new Exception("Document '{$after}' for the 'after' value not found.", 400); } } diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 6fc426534..144170755 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -88,7 +88,7 @@ App::get('/v1/functions') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the function used to return functions listed after. Should be used for efficient pagination working with many functions.', true) + ->param('after', '', 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.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') @@ -102,7 +102,7 @@ App::get('/v1/functions') $afterFunction = $dbForInternal->getDocument('functions', $after); if ($afterFunction->isEmpty()) { - throw new Exception('Function for after not found', 400); + throw new Exception("Function '{$after}' for the 'after' value not found.", 400); } } @@ -515,7 +515,7 @@ App::get('/v1/functions/:functionId/tags') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the tag used to return tags listed after. Should be used for efficient pagination working with many tags.', true) + ->param('after', '', new UID(), 'ID of the tag used as the starting point for the query, excluding the tag itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') @@ -535,7 +535,7 @@ App::get('/v1/functions/:functionId/tags') $afterTag = $dbForInternal->getDocument('tags', $after); if ($afterTag->isEmpty()) { - throw new Exception('Tag for after not found', 400); + throw new Exception("Tag '{$after}' for the 'after' value not found.", 400); } } @@ -766,7 +766,7 @@ App::get('/v1/functions/:functionId/executions') ->param('functionId', '', new UID(), 'Function unique ID.') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the execution used to return executions listed after. Should be used for efficient pagination working with many executions.', true) + ->param('after', '', 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.', true) ->inject('response') ->inject('dbForInternal') ->action(function ($functionId, $limit, $offset, $after, $response, $dbForInternal) { @@ -785,7 +785,7 @@ App::get('/v1/functions/:functionId/executions') $afterExecution = $dbForInternal->getDocument('executions', $after); if ($afterExecution->isEmpty()) { - throw new Exception('Execution for after not found', 400); + throw new Exception("Execution '{$after}' for the 'after' value not found.", 400); } } diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 7ac955701..e34c94883 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -164,7 +164,7 @@ App::get('/v1/projects') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the project used to return projects listed after. Should be used for efficient pagination working with many projects.', true) + ->param('after', '', new UID(), 'ID of the project used as the starting point for the query, excluding the project itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForConsole') @@ -178,7 +178,7 @@ App::get('/v1/projects') $afterProject = $dbForConsole->getDocument('projects', $after); if ($afterProject->isEmpty()) { - throw new Exception('Project for after not found', 400); + throw new Exception("Project '{$after}' for the 'after' value not found.", 400); } } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 37df8f6f2..5a5c43de5 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -171,7 +171,7 @@ App::get('/v1/storage/files') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the file used to return files listed after. Should be used for efficient pagination working with many files.', true) + ->param('after', '', 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.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') @@ -185,7 +185,7 @@ App::get('/v1/storage/files') $afterFile = $dbForInternal->getDocument('files', $after); if ($afterFile->isEmpty()) { - throw new Exception('File for after not found', 400); + throw new Exception("File '{$after}' for the 'after' value not found.", 400); } } diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index cce2e835e..569940c42 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -99,7 +99,7 @@ App::get('/v1/teams') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the team used to return teams listed after. Should be used for efficient pagination working with many teams.', true) + ->param('after', '', 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.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') @@ -113,7 +113,7 @@ App::get('/v1/teams') $afterTeam = $dbForInternal->getDocument('teams', $after); if ($afterTeam->isEmpty()) { - throw new Exception('Team for after not found', 400); + throw new Exception("Team '{$after}' for the 'after' value not found.", 400); } } @@ -424,7 +424,7 @@ App::get('/v1/teams/:teamId/memberships') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the file used to return files listed after. Should be used for efficient pagination working with many files.', true) + ->param('after', '', 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.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') @@ -442,7 +442,7 @@ App::get('/v1/teams/:teamId/memberships') $afterMembership = $dbForInternal->getDocument('memberships', $after); if ($afterMembership->isEmpty()) { - throw new Exception('Membership for after not found', 400); + throw new Exception("Membership '{$after}' for the 'after' value not found.", 400); } } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index a51dbf668..11beca048 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -83,7 +83,7 @@ App::get('/v1/users') ->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, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) - ->param('after', '', new UID(), 'ID of the user used to return users listed after. Should be used for efficient pagination working with many users.', true) + ->param('after', '', new UID(), 'ID of the user used as the starting point for the query, excluding the user itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') From ba5eb5208441f565fb535f131e54c90963d7ffd1 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 13 Aug 2021 10:08:10 +0200 Subject: [PATCH 21/21] chore(composer): update utopia audit and abuse --- composer.json | 2 +- composer.lock | 56 +++++++++++++++++++++------------------------------ 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/composer.json b/composer.json index 4a5685b4c..ba45139b9 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "dev-main as 0.6.1", + "utopia-php/database": "0.7.*", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index 844a74639..db07f5df2 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": "6b3c314f3faa9c3aff868eaf7f6f3cbb", + "content-hash": "7de5dc8a9fe3cbc14696c685d1cdddee", "packages": [ { "name": "adhocore/jwt", @@ -1666,22 +1666,22 @@ }, { "name": "utopia-php/abuse", - "version": "0.6.1", + "version": "0.6.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "c9078aa3a87750d66060f0ed7642e03e5815da17" + "reference": "4cd9c16610f7398d2e1737663ef682fa721ae736" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/c9078aa3a87750d66060f0ed7642e03e5815da17", - "reference": "c9078aa3a87750d66060f0ed7642e03e5815da17", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/4cd9c16610f7398d2e1737663ef682fa721ae736", + "reference": "4cd9c16610f7398d2e1737663ef682fa721ae736", "shasum": "" }, "require": { "ext-pdo": "*", "php": ">=7.4", - "utopia-php/database": "0.6.*" + "utopia-php/database": "0.7.*" }, "require-dev": { "phpunit/phpunit": "^9.4", @@ -1713,9 +1713,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.6.1" + "source": "https://github.com/utopia-php/abuse/tree/0.6.2" }, - "time": "2021-08-03T19:31:07+00:00" + "time": "2021-08-13T07:52:34+00:00" }, { "name": "utopia-php/analytics", @@ -1774,22 +1774,22 @@ }, { "name": "utopia-php/audit", - "version": "0.6.1", + "version": "0.6.2", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "971dcd5c88309656df31ac20f326d3ac8b555594" + "reference": "2ec39a53eb98a5f9d230550ad56c7c04de5d77df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/971dcd5c88309656df31ac20f326d3ac8b555594", - "reference": "971dcd5c88309656df31ac20f326d3ac8b555594", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/2ec39a53eb98a5f9d230550ad56c7c04de5d77df", + "reference": "2ec39a53eb98a5f9d230550ad56c7c04de5d77df", "shasum": "" }, "require": { "ext-pdo": "*", "php": ">=7.4", - "utopia-php/database": "0.6.*" + "utopia-php/database": "0.7.*" }, "require-dev": { "phpunit/phpunit": "^9.3", @@ -1821,9 +1821,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.6.1" + "source": "https://github.com/utopia-php/audit/tree/0.6.2" }, - "time": "2021-08-03T19:29:34+00:00" + "time": "2021-08-13T08:05:20+00:00" }, { "name": "utopia-php/cache", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "dev-main", + "version": "0.7.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "bd765cd67e042defb8d0a15ef9a400784d6beb24" + "reference": "46c4a99347397e362a9429826e1888b0aefb2056" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/bd765cd67e042defb8d0a15ef9a400784d6beb24", - "reference": "bd765cd67e042defb8d0a15ef9a400784d6beb24", + "url": "https://api.github.com/repos/utopia-php/database/zipball/46c4a99347397e362a9429826e1888b0aefb2056", + "reference": "46c4a99347397e362a9429826e1888b0aefb2056", "shasum": "" }, "require": { @@ -2011,7 +2011,6 @@ "utopia-php/cli": "^0.11.0", "vimeo/psalm": "4.0.1" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2042,9 +2041,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/main" + "source": "https://github.com/utopia-php/database/tree/0.7.0" }, - "time": "2021-08-10T06:09:02+00:00" + "time": "2021-08-10T19:09:58+00:00" }, { "name": "utopia-php/domains", @@ -6255,18 +6254,9 @@ "time": "2015-12-17T08:42:14+00:00" } ], - "aliases": [ - { - "package": "utopia-php/database", - "version": "dev-main", - "alias": "0.6.1", - "alias_normalized": "0.6.1.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": {