From ead77d6cadf270edb1528f24b41a48875677786c Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 21 Jul 2023 00:20:53 +0530 Subject: [PATCH 01/27] Add support for queries in List attributes endpoint --- app/controllers/api/databases.php | 50 ++++++++++++++++--- .../Database/Validator/Queries/Attributes.php | 23 +++++++++ .../e2e/Services/Databases/DatabasesBase.php | 18 ++++++- 3 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f3726c39e7..008b5f730f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -8,6 +8,7 @@ use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Database\Validator\Queries\Attributes; use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; use Appwrite\Utopia\Response; @@ -1657,9 +1658,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_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/databases#databasesCreateCollection).') + ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). 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) ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); @@ -1673,12 +1675,48 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attributes = $collection->getAttribute('attributes'); + $queries = Query::parseQueries($queries); + \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - $response->dynamic(new Document([ - 'total' => \count($attributes), - 'attributes' => $attributes - ]), Response::MODEL_ATTRIBUTE_LIST); + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); + + if ($cursor) { + $attributeId = $cursor->getValue(); + + $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $attributeId)); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $attributes = $dbForProject->find('attributes', $queries); + + //Add relationship data from options to attributes as it loses options during response setup + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $attribute->getAttribute('options'); + $attribute->setAttribute('relatedCollection', $options['relatedCollection']); + $attribute->setAttribute('relationType', $options['relationType']); + $attribute->setAttribute('twoWay', $options['twoWay']); + $attribute->setAttribute('twoWayKey', $options['twoWayKey']); + $attribute->setAttribute('side', $options['side']); + $attribute->setAttribute('onDelete', $options['onDelete']); + } + } + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT), + 'attributes' => $attributes, + ]), Response::MODEL_ATTRIBUTE_LIST); }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php new file mode 100644 index 0000000000..44135a3a79 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -0,0 +1,23 @@ +client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => ['equal("type", "string")'], + ]); + $this->assertEquals(200, $attributes['headers']['status-code']); + $this->assertEquals(3, $attributes['body']['total']); + } + /** * @depends testCreateAttributes */ @@ -698,7 +715,6 @@ trait DatabasesBase $this->assertEquals(10, $attributes['body']['total']); $attributes = $attributes['body']['attributes']; - $this->assertIsArray($attributes); $this->assertCount(10, $attributes); From a842d7eeae0010c9fde8b309fe5a46c5092a461d Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 21 Jul 2023 00:26:21 +0530 Subject: [PATCH 02/27] fix queries param description --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 008b5f730f..9054ec3612 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1658,7 +1658,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_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/databases#databasesCreateCollection).') - ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). 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('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). 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(', ', Attributes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { From 165268cb71c92fbbac625213d0d07ec38d005eb8 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 21 Jul 2023 08:33:36 +0530 Subject: [PATCH 03/27] remove unnecessary db call --- app/controllers/api/databases.php | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 9054ec3612..e355843842 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1663,18 +1663,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); - } - - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - - if ($collection->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); - } - $queries = Query::parseQueries($queries); \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); @@ -1689,13 +1677,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') if ($cursor) { $attributeId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $attributeId)); + $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$attributeId]), Query::limit(1)])); - if ($cursorDocument->isEmpty()) { + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found."); } - $cursor->setValue($cursorDocument); + $cursor->setValue($cursorDocument[0]); } $attributes = $dbForProject->find('attributes', $queries); From a6abc7c4e868b0b3812a5e3ec3cf930bc80aaae2 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 21 Jul 2023 16:40:44 +0530 Subject: [PATCH 04/27] add support of queries in list indexes --- app/controllers/api/databases.php | 47 ++++++++++++------- .../Database/Validator/Queries/Indexes.php | 21 +++++++++ .../e2e/Services/Databases/DatabasesBase.php | 17 +++++++ 3 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index e355843842..cf4a1bd349 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -11,6 +11,7 @@ use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Attributes; use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; +use Appwrite\Utopia\Database\Validator\Queries\Indexes; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; use Utopia\App; @@ -1664,11 +1665,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { $queries = Query::parseQueries($queries); + foreach ($queries as $query) { + if ($query->getMethod() === Query::TYPE_SELECT) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, "Select queries are not valid."); + } + } \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } // Get cursor document if there was a cursor query $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); @@ -2514,26 +2517,38 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->label('sdk.response.model', Response::MODEL_INDEX_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/databases#databasesCreateCollection).') + ->param('queries', [], new Indexes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). 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(', ', Indexes::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); - - if ($database->isEmpty()) { - throw new Exception(Exception::DATABASE_NOT_FOUND); + $queries = Query::parseQueries($queries); + foreach ($queries as $query) { + if ($query->getMethod() === Query::TYPE_SEARCH) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, "Select queries are not valid."); + } } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - if ($collection->isEmpty()) { - throw new Exception(Exception::COLLECTION_NOT_FOUND); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); + + if ($cursor) { + $indexId = $cursor->getValue(); + + $cursorDocument = Authorization::skip(fn() => $dbForProject->find('indexes', [Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$indexId]), Query::limit(1)])); + + if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Index '{$indexId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument[0]); } - - $indexes = $collection->getAttribute('indexes'); - + $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ - 'total' => \count($indexes), - 'indexes' => $indexes, + 'total' => $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT), + 'indexes' => $dbForProject->find('indexes', $queries), ]), Response::MODEL_INDEX_LIST); }); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php new file mode 100644 index 0000000000..c7486d1a88 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php @@ -0,0 +1,21 @@ +client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => ['equal("type", "key")'], + ]); + $this->assertEquals(200, $indexes['headers']['status-code']); + $this->assertEquals(3, $indexes['body']['total']); + } + /** * @depends testCreateIndexes */ From 98a226dae9ef68abb62ea221b4a3deb8585ddc9d Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Tue, 25 Jul 2023 00:03:58 +0530 Subject: [PATCH 05/27] adds collection and database calls for better error messages --- app/controllers/api/databases.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index cf4a1bd349..f09ed55020 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1664,6 +1664,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + + + if ($collection->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + $queries = Query::parseQueries($queries); foreach ($queries as $query) { if ($query->getMethod() === Query::TYPE_SELECT) { @@ -2522,6 +2535,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { + $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); + + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + + if ($collection->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + $queries = Query::parseQueries($queries); foreach ($queries as $query) { if ($query->getMethod() === Query::TYPE_SEARCH) { From 301af0d3fe066c57bf07260f708c2bcfe3700dea Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 26 Jul 2023 11:37:23 +0530 Subject: [PATCH 06/27] fixes lint issues and adds status in list attributes query support --- app/controllers/api/databases.php | 27 ++++++++++++------- .../Database/Validator/Queries/Attributes.php | 3 ++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f09ed55020..66fb35879e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1672,7 +1672,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -1680,7 +1679,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $queries = Query::parseQueries($queries); foreach ($queries as $query) { if ($query->getMethod() === Query::TYPE_SELECT) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, "Select queries are not valid."); + throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Select queries are not valid.'); } } \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); @@ -1693,7 +1692,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') if ($cursor) { $attributeId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$attributeId]), Query::limit(1)])); + $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [ + Query::equal('collectionId', [$collectionId]), + Query::equal('databaseId', [$databaseId]), + Query::equal('key', [$attributeId]), + Query::limit(1), + ])); if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found."); @@ -1716,11 +1720,11 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $attribute->setAttribute('onDelete', $options['onDelete']); } } - $filterQueries = Query::groupByType($queries)['filters']; - $response->dynamic(new Document([ + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ 'total' => $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT), 'attributes' => $attributes, - ]), Response::MODEL_ATTRIBUTE_LIST); + ]), Response::MODEL_ATTRIBUTE_LIST); }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') @@ -2550,7 +2554,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $queries = Query::parseQueries($queries); foreach ($queries as $query) { if ($query->getMethod() === Query::TYPE_SEARCH) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, "Select queries are not valid."); + throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Select queries are not valid.'); } } \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); @@ -2561,8 +2565,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') if ($cursor) { $indexId = $cursor->getValue(); - - $cursorDocument = Authorization::skip(fn() => $dbForProject->find('indexes', [Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$indexId]), Query::limit(1)])); + $cursorDocument = Authorization::skip(fn() => $dbForProject->find('indexes', [ + Query::equal('collectionId', [$collectionId]), + Query::equal('databaseId', [$databaseId]), + Query::equal('key', [$indexId]), + Query::limit(1) + ])); if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Index '{$indexId}' for the 'cursor' value not found."); @@ -2570,6 +2578,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $cursor->setValue($cursorDocument[0]); } + $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ 'total' => $dbForProject->count('indexes', $filterQueries, APP_LIMIT_COUNT), diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 44135a3a79..c6549e73f8 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -9,7 +9,8 @@ class Attributes extends Base 'type', 'size', 'required', - 'array' + 'array', + 'status' ]; /** From 0c758a282abac7e78a06257ffd7bf053d33abf39 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 27 Jul 2023 01:30:15 +0530 Subject: [PATCH 07/27] adds error attribute in queries for indexes and attributes --- src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php | 3 ++- src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index c6549e73f8..4a35c82b73 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -10,7 +10,8 @@ class Attributes extends Base 'size', 'required', 'array', - 'status' + 'status', + 'error' ]; /** diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php index c7486d1a88..56bc696706 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php @@ -8,6 +8,7 @@ class Indexes extends Base 'key', 'type', 'status', + 'error' ]; /** From 484ad8280e3c85800abafb7b02be1cb4c3d63800 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 27 Jul 2023 02:29:14 +0530 Subject: [PATCH 08/27] fixes test case assertion --- tests/e2e/Services/Databases/DatabasesBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index fa7577781d..ffba8a63e6 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -330,7 +330,7 @@ trait DatabasesBase 'queries' => ['equal("type", "string")'], ]); $this->assertEquals(200, $attributes['headers']['status-code']); - $this->assertEquals(3, $attributes['body']['total']); + $this->assertEquals(4, $attributes['body']['total']); } /** From 27e0ec339a0438df71444e0f0da5fbb179dac915 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 27 Jul 2023 02:59:06 +0530 Subject: [PATCH 09/27] fix more lint issues --- app/controllers/api/databases.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 66fb35879e..75ea368fcd 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1684,10 +1684,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') } \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); - $cursor = reset($cursor); + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = reset($cursor); if ($cursor) { $attributeId = $cursor->getValue(); From 1d558fa5f581f00de3ddd3d15ec799232626b021 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 3 Aug 2023 17:34:28 +0530 Subject: [PATCH 10/27] Add select queries support to list indexes and list attributes endpoint --- app/controllers/api/databases.php | 68 +++++++----- app/controllers/shared/api.php | 6 +- composer.json | 6 +- composer.lock | 101 +++++++++--------- .../Database/Validator/Queries/Indexes.php | 5 +- src/Appwrite/Utopia/Response.php | 90 ++++++++++------ 6 files changed, 163 insertions(+), 113 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 75ea368fcd..f5d8f9ebd6 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1676,54 +1676,77 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $queries = Query::parseQueries($queries); - foreach ($queries as $query) { + $queriesFromRequest = Query::parseQueries($queries); + + // Add type property in query if select query exists and type property doesn't exist as type is required for response model + $hasDetailsinQuery = [ + 'selectQuery' => false, + 'typeAttributeInSelectQuery' => false, + ]; + foreach ($queriesFromRequest as $query) { if ($query->getMethod() === Query::TYPE_SELECT) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Select queries are not valid.'); + $hasDetailsinQuery['selectQuery'] = true; + } + if(\array_search('type', $query->getValues())){ + $hasDetailsinQuery['typeAttributeInSelectQuery'] = true; } } - \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); + $transformedQueries = $queriesFromRequest; + if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) { + \array_push($transformedQueries, Query::select(['type'])); + } + + \array_push($transformedQueries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = Query::getByType($transformedQueries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); $cursor = reset($cursor); if ($cursor) { $attributeId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [ Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]), Query::equal('key', [$attributeId]), Query::limit(1), ])); - if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found."); } - $cursor->setValue($cursorDocument[0]); } - - $attributes = $dbForProject->find('attributes', $queries); + + $attributes = $dbForProject->find('attributes', $transformedQueries); + $filterQueries = Query::groupByType($transformedQueries)['filters']; + $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); //Add relationship data from options to attributes as it loses options during response setup foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) { $options = $attribute->getAttribute('options'); - $attribute->setAttribute('relatedCollection', $options['relatedCollection']); - $attribute->setAttribute('relationType', $options['relationType']); - $attribute->setAttribute('twoWay', $options['twoWay']); - $attribute->setAttribute('twoWayKey', $options['twoWayKey']); - $attribute->setAttribute('side', $options['side']); - $attribute->setAttribute('onDelete', $options['onDelete']); + if(!\is_null($options)){ + $attribute->setAttribute('relatedCollection', $options['relatedCollection']); + $attribute->setAttribute('relationType', $options['relationType']); + $attribute->setAttribute('twoWay', $options['twoWay']); + $attribute->setAttribute('twoWayKey', $options['twoWayKey']); + $attribute->setAttribute('side', $options['side']); + $attribute->setAttribute('onDelete', $options['onDelete']); + } } } - $filterQueries = Query::groupByType($queries)['filters']; - $response->dynamic(new Document([ - 'total' => $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT), + $output = $response->output(new Document([ + 'total' => $total, 'attributes' => $attributes, ]), Response::MODEL_ATTRIBUTE_LIST); + + // If type Attribute didn't exist in select query we need to remove type attribute from attribute list + if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) { + foreach($output['attributes'] as &$attribute) { + unset($attribute['type']); + } + } + + $response->static($output); }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') @@ -2551,11 +2574,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') } $queries = Query::parseQueries($queries); - foreach ($queries as $query) { - if ($query->getMethod() === Query::TYPE_SEARCH) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Select queries are not valid.'); - } - } \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); // Get cursor document if there was a cursor query diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index c89bf0252e..566a800752 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -207,9 +207,11 @@ App::init() $deletes->setProject($project); $database->setProject($project); - $dbForProject->on(Database::EVENT_DOCUMENT_CREATE, fn ($event, Document $document) => $databaseListener($event, $document, $usage)); + $calculateUsage = fn ($event, Document $document) => $databaseListener($event, $document, $usage); - $dbForProject->on(Database::EVENT_DOCUMENT_DELETE, fn ($event, Document $document) => $databaseListener($event, $document, $usage)); + $dbForProject->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', $calculateUsage); + + $dbForProject->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', $calculateUsage); $useCache = $route->getLabel('cache', false); diff --git a/composer.json b/composer.json index 8070096898..6c31fa8873 100644 --- a/composer.json +++ b/composer.json @@ -43,13 +43,13 @@ "ext-sockets": "*", "appwrite/php-clamav": "2.0.*", "appwrite/php-runtimes": "0.11.*", - "utopia-php/abuse": "0.27.*", + "utopia-php/abuse": "0.29.*", "utopia-php/analytics": "0.2.*", - "utopia-php/audit": "0.29.*", + "utopia-php/audit": "0.31.*", "utopia-php/cache": "0.8.*", "utopia-php/cli": "0.13.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.38.*", + "utopia-php/database": "0.40.*", "utopia-php/domains": "1.1.*", "utopia-php/framework": "0.28.*", "utopia-php/image": "0.5.*", diff --git a/composer.lock b/composer.lock index 5a25c90dc4..c9d6d1295f 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": "c41be9b81d4ee69cf915be4c7ba37975", + "content-hash": "1dde9b87dc894a8ab765cad3567bfe7c", "packages": [ { "name": "adhocore/jwt", @@ -994,16 +994,16 @@ }, { "name": "matomo/device-detector", - "version": "6.1.3", + "version": "6.1.4", "source": { "type": "git", "url": "https://github.com/matomo-org/device-detector.git", - "reference": "3e0fac7e77f3faadc3858fea9f5fa7efeb9cf239" + "reference": "74f6c4f6732b3ad6cdf25560746841d522969112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/3e0fac7e77f3faadc3858fea9f5fa7efeb9cf239", - "reference": "3e0fac7e77f3faadc3858fea9f5fa7efeb9cf239", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/74f6c4f6732b3ad6cdf25560746841d522969112", + "reference": "74f6c4f6732b3ad6cdf25560746841d522969112", "shasum": "" }, "require": { @@ -1059,7 +1059,7 @@ "source": "https://github.com/matomo-org/matomo", "wiki": "https://dev.matomo.org/" }, - "time": "2023-06-06T11:58:07+00:00" + "time": "2023-08-02T08:48:53+00:00" }, { "name": "mongodb/mongodb", @@ -1804,23 +1804,23 @@ }, { "name": "utopia-php/abuse", - "version": "0.27.0", + "version": "0.29.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "d1115f5843e903ffaba9c23e450b33c0fe265ae0" + "reference": "7589d0c7a6f685fcbb02d57875f034bd233ec262" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/d1115f5843e903ffaba9c23e450b33c0fe265ae0", - "reference": "d1115f5843e903ffaba9c23e450b33c0fe265ae0", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/7589d0c7a6f685fcbb02d57875f034bd233ec262", + "reference": "7589d0c7a6f685fcbb02d57875f034bd233ec262", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.38.*" + "utopia-php/database": "0.40.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1847,9 +1847,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.27.0" + "source": "https://github.com/utopia-php/abuse/tree/0.29.0" }, - "time": "2023-07-15T00:53:50+00:00" + "time": "2023-08-03T08:22:12+00:00" }, { "name": "utopia-php/analytics", @@ -1908,21 +1908,21 @@ }, { "name": "utopia-php/audit", - "version": "0.29.0", + "version": "0.31.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "5318538f457bf73623629345c98ea06371ca5dd4" + "reference": "f1b0165fccb6ec665f7ae947bfed56a8f6b877cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/5318538f457bf73623629345c98ea06371ca5dd4", - "reference": "5318538f457bf73623629345c98ea06371ca5dd4", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/f1b0165fccb6ec665f7ae947bfed56a8f6b877cb", + "reference": "f1b0165fccb6ec665f7ae947bfed56a8f6b877cb", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.38.*" + "utopia-php/database": "0.40.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1949,9 +1949,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.29.0" + "source": "https://github.com/utopia-php/audit/tree/0.31.0" }, - "time": "2023-07-15T00:51:10+00:00" + "time": "2023-08-03T08:22:32+00:00" }, { "name": "utopia-php/cache", @@ -2108,16 +2108,16 @@ }, { "name": "utopia-php/database", - "version": "0.38.0", + "version": "0.40.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "59e4684cf87e03c12dab9240158c1dfc6888e534" + "reference": "ec586ba1c5fc83856df4feaa05464da72b72ee0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/59e4684cf87e03c12dab9240158c1dfc6888e534", - "reference": "59e4684cf87e03c12dab9240158c1dfc6888e534", + "url": "https://api.github.com/repos/utopia-php/database/zipball/ec586ba1c5fc83856df4feaa05464da72b72ee0d", + "reference": "ec586ba1c5fc83856df4feaa05464da72b72ee0d", "shasum": "" }, "require": { @@ -2158,9 +2158,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.38.0" + "source": "https://github.com/utopia-php/database/tree/0.40.0" }, - "time": "2023-07-14T07:49:38+00:00" + "time": "2023-08-03T08:01:37+00:00" }, { "name": "utopia-php/domains", @@ -3785,16 +3785,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.22.1", + "version": "1.23.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0" + "reference": "a2b24135c35852b348894320d47b3902a94bc494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/65c39594fbd8c67abfc68bb323f86447bab79cc0", - "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a2b24135c35852b348894320d47b3902a94bc494", + "reference": "a2b24135c35852b348894320d47b3902a94bc494", "shasum": "" }, "require": { @@ -3826,22 +3826,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.22.1" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.0" }, - "time": "2023-06-29T20:46:06+00:00" + "time": "2023-07-23T22:17:56+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.26", + "version": "9.2.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1", + "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1", "shasum": "" }, "require": { @@ -3897,7 +3897,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27" }, "funding": [ { @@ -3905,7 +3906,7 @@ "type": "github" } ], - "time": "2023-03-06T12:58:08+00:00" + "time": "2023-07-26T13:44:30+00:00" }, { "name": "phpunit/php-file-iterator", @@ -4757,16 +4758,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -4809,7 +4810,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -4817,7 +4818,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -5580,16 +5581,16 @@ }, { "name": "twig/twig", - "version": "v3.6.1", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "7e7d5839d4bec168dfeef0ac66d5c5a2edbabffd" + "reference": "5cf942bbab3df42afa918caeba947f1b690af64b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/7e7d5839d4bec168dfeef0ac66d5c5a2edbabffd", - "reference": "7e7d5839d4bec168dfeef0ac66d5c5a2edbabffd", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/5cf942bbab3df42afa918caeba947f1b690af64b", + "reference": "5cf942bbab3df42afa918caeba947f1b690af64b", "shasum": "" }, "require": { @@ -5635,7 +5636,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.6.1" + "source": "https://github.com/twigphp/Twig/tree/v3.7.0" }, "funding": [ { @@ -5647,7 +5648,7 @@ "type": "tidelift" } ], - "time": "2023-06-08T12:52:13+00:00" + "time": "2023-07-26T07:16:09+00:00" } ], "aliases": [], diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php index 56bc696706..d9290e5737 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Indexes.php @@ -8,7 +8,8 @@ class Indexes extends Base 'key', 'type', 'status', - 'error' + 'attributes', + 'error', ]; /** @@ -17,6 +18,6 @@ class Indexes extends Base */ public function __construct() { - parent::__construct('attributes', self::ALLOWED_ATTRIBUTES); + parent::__construct('indexes', self::ALLOWED_ATTRIBUTES); } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index e65f65cd52..51df3c2f37 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -458,6 +458,33 @@ class Response extends SwooleResponse } } + /** + * Sends the response based on content type + * + * @param array $ouput + * + * return void + * @throws Exception + */ + public function static(array $output): void + { + switch ($this->getContentType()) { + case self::CONTENT_TYPE_JSON: + $this->json(!empty($output) ? $output : new \stdClass()); + break; + + case self::CONTENT_TYPE_YAML: + $this->yaml(!empty($output) ? $output : new \stdClass()); + break; + + case self::CONTENT_TYPE_NULL: + break; + + default: + $this->json(!empty($output) ? $output : new \stdClass()); + } + } + /** * Generate valid response object from document data * @@ -491,45 +518,46 @@ class Response extends SwooleResponse } } - if ($rule['array']) { - if (!is_array($document[$key])) { - throw new Exception($key . ' must be an array of type ' . $rule['type']); - } - - foreach ($document[$key] as $index => $item) { - if ($item instanceof Document) { - if (\is_array($rule['type'])) { - foreach ($rule['type'] as $type) { - $condition = false; - foreach ($this->getModel($type)->conditions as $attribute => $val) { - $condition = $item->getAttribute($attribute) === $val; - if (!$condition) { + if ($rule['required'] && !(\is_null($document[$key]))) { + if ($rule['array']) { + if (!is_array($document[$key])) { + throw new Exception($key . ' must be an array of type ' . $rule['type']); + } + + foreach ($document[$key] as $index => $item) { + if ($item instanceof Document) { + if (\is_array($rule['type'])) { + foreach ($rule['type'] as $type) { + $condition = false; + foreach ($this->getModel($type)->conditions as $attribute => $val) { + $condition = $item->getAttribute($attribute) === $val; + if (!$condition) { + break; + } + } + if ($condition) { + $ruleType = $type; break; } } - if ($condition) { - $ruleType = $type; - break; - } + } else { + $ruleType = $rule['type']; } - } else { - $ruleType = $rule['type']; + + if (!array_key_exists($ruleType, $this->models)) { + throw new Exception('Missing model for rule: ' . $ruleType); + } + + $data[$key][$index] = $this->output($item, $ruleType); } - - if (!array_key_exists($ruleType, $this->models)) { - throw new Exception('Missing model for rule: ' . $ruleType); - } - - $data[$key][$index] = $this->output($item, $ruleType); + } + } else { + if ($document[$key] instanceof Document) { + $data[$key] = $this->output($data[$key], $rule['type']); } } - } else { - if ($document[$key] instanceof Document) { - $data[$key] = $this->output($data[$key], $rule['type']); - } + $output[$key] = $data[$key]; } - - $output[$key] = $data[$key]; } $this->payload = $output; From ea57a303d0fe3b447f047214e621fbba327ccbdf Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 3 Aug 2023 17:39:13 +0530 Subject: [PATCH 11/27] lint fixes --- app/controllers/api/databases.php | 12 ++++++------ src/Appwrite/Utopia/Response.php | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 32749dcd0e..bfda14a492 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1676,7 +1676,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $queriesFromRequest = Query::parseQueries($queries); + $queriesFromRequest = Query::parseQueries($queries); // Add type property in query if select query exists and type property doesn't exist as type is required for response model $hasDetailsinQuery = [ @@ -1687,7 +1687,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') if ($query->getMethod() === Query::TYPE_SELECT) { $hasDetailsinQuery['selectQuery'] = true; } - if(\array_search('type', $query->getValues())){ + if (\array_search('type', $query->getValues())) { $hasDetailsinQuery['typeAttributeInSelectQuery'] = true; } } @@ -1715,16 +1715,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') } $cursor->setValue($cursorDocument[0]); } - + $attributes = $dbForProject->find('attributes', $transformedQueries); $filterQueries = Query::groupByType($transformedQueries)['filters']; $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); //Add relationship data from options to attributes as it loses options during response setup foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP ) { + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); - if(!\is_null($options)){ + if (!\is_null($options)) { $attribute->setAttribute('relatedCollection', $options['relatedCollection']); $attribute->setAttribute('relationType', $options['relationType']); $attribute->setAttribute('twoWay', $options['twoWay']); @@ -1741,7 +1741,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') // If type Attribute didn't exist in select query we need to remove type attribute from attribute list if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) { - foreach($output['attributes'] as &$attribute) { + foreach ($output['attributes'] as &$attribute) { unset($attribute['type']); } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 51df3c2f37..0329e4546f 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -466,7 +466,7 @@ class Response extends SwooleResponse * return void * @throws Exception */ - public function static(array $output): void + public function static(array $output): void { switch ($this->getContentType()) { case self::CONTENT_TYPE_JSON: @@ -523,7 +523,7 @@ class Response extends SwooleResponse if (!is_array($document[$key])) { throw new Exception($key . ' must be an array of type ' . $rule['type']); } - + foreach ($document[$key] as $index => $item) { if ($item instanceof Document) { if (\is_array($rule['type'])) { @@ -543,11 +543,11 @@ class Response extends SwooleResponse } else { $ruleType = $rule['type']; } - + if (!array_key_exists($ruleType, $this->models)) { throw new Exception('Missing model for rule: ' . $ruleType); } - + $data[$key][$index] = $this->output($item, $ruleType); } } From 91e434b3d6557438d3e7102e571c1ab8edbb9efd Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 4 Aug 2023 14:01:08 +0530 Subject: [PATCH 12/27] optimize if condition in response output method --- composer.lock | 36 ++++++++++++++++---------------- src/Appwrite/Utopia/Response.php | 4 ++-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/composer.lock b/composer.lock index 528fdb0f59..dcfe117923 100644 --- a/composer.lock +++ b/composer.lock @@ -607,16 +607,16 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", "shasum": "" }, "require": { @@ -670,7 +670,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.0" + "source": "https://github.com/guzzle/promises/tree/2.0.1" }, "funding": [ { @@ -686,20 +686,20 @@ "type": "tidelift" } ], - "time": "2023-05-21T13:50:22+00:00" + "time": "2023-08-03T15:11:55+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.5.0", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", + "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", "shasum": "" }, "require": { @@ -786,7 +786,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.5.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.0" }, "funding": [ { @@ -802,7 +802,7 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:11:26+00:00" + "time": "2023-08-03T15:06:02+00:00" }, { "name": "influxdb/influxdb-php", @@ -3785,16 +3785,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.23.0", + "version": "1.23.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "a2b24135c35852b348894320d47b3902a94bc494" + "reference": "846ae76eef31c6d7790fac9bc399ecee45160b26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a2b24135c35852b348894320d47b3902a94bc494", - "reference": "a2b24135c35852b348894320d47b3902a94bc494", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/846ae76eef31c6d7790fac9bc399ecee45160b26", + "reference": "846ae76eef31c6d7790fac9bc399ecee45160b26", "shasum": "" }, "require": { @@ -3826,9 +3826,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.1" }, - "time": "2023-07-23T22:17:56+00:00" + "time": "2023-08-03T16:32:59+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 0329e4546f..964d93ae1e 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -518,7 +518,7 @@ class Response extends SwooleResponse } } - if ($rule['required'] && !(\is_null($document[$key]))) { + if ($data->isSet($key)) { if ($rule['array']) { if (!is_array($document[$key])) { throw new Exception($key . ' must be an array of type ' . $rule['type']); @@ -556,8 +556,8 @@ class Response extends SwooleResponse $data[$key] = $this->output($data[$key], $rule['type']); } } - $output[$key] = $data[$key]; } + $output[$key] = $data[$key]; } $this->payload = $output; From 4dc897686335b37c8b18270f47ac70576c8b9bee Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 4 Aug 2023 14:53:56 +0530 Subject: [PATCH 13/27] add queries type for sdk generation --- src/Appwrite/Specification/Format/OpenAPI3.php | 2 ++ src/Appwrite/Specification/Format/Swagger2.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index bf0293d5af..81999c06ad 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -343,6 +343,8 @@ class OpenAPI3 extends Format case 'Utopia\Validator\ArrayList': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Collections': + case 'Appwrite\Utopia\Database\Validator\Queries\Indexes': + case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': case 'Utopia\Database\Validator\Queries\Documents': diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 60974bef85..ac489864eb 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -342,6 +342,8 @@ class Swagger2 extends Format case 'Utopia\Validator\ArrayList': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Collections': + case 'Appwrite\Utopia\Database\Validator\Queries\Indexes': + case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': case 'Utopia\Database\Validator\Queries\Documents': From 52e800cc599947933d275c7374a885ff0ea7290c Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 8 Aug 2023 02:56:20 +0530 Subject: [PATCH 14/27] refactor according to review feedback --- app/controllers/api/databases.php | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index bfda14a492..9279d4d115 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1676,30 +1676,28 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $queriesFromRequest = Query::parseQueries($queries); + $queries = Query::parseQueries($queries); // Add type property in query if select query exists and type property doesn't exist as type is required for response model - $hasDetailsinQuery = [ - 'selectQuery' => false, - 'typeAttributeInSelectQuery' => false, - ]; - foreach ($queriesFromRequest as $query) { + $hasSelect = false; + $hasTypeAttribute = false; + foreach ($queries as $query) { if ($query->getMethod() === Query::TYPE_SELECT) { - $hasDetailsinQuery['selectQuery'] = true; + $hasSelect = true; } if (\array_search('type', $query->getValues())) { - $hasDetailsinQuery['typeAttributeInSelectQuery'] = true; + $hasTypeAttribute = true; } } - $transformedQueries = $queriesFromRequest; - if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) { - \array_push($transformedQueries, Query::select(['type'])); + + if ($hasSelect && !$hasTypeAttribute) { + \array_push($queries, Query::select(['type'])); } - \array_push($transformedQueries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); + \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); // Get cursor document if there was a cursor query - $cursor = Query::getByType($transformedQueries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); + $cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]); $cursor = reset($cursor); if ($cursor) { @@ -1716,8 +1714,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $cursor->setValue($cursorDocument[0]); } - $attributes = $dbForProject->find('attributes', $transformedQueries); - $filterQueries = Query::groupByType($transformedQueries)['filters']; + $attributes = $dbForProject->find('attributes', $queries); + $filterQueries = Query::groupByType($queries)['filters']; $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); //Add relationship data from options to attributes as it loses options during response setup @@ -1740,7 +1738,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ]), Response::MODEL_ATTRIBUTE_LIST); // If type Attribute didn't exist in select query we need to remove type attribute from attribute list - if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) { + if ($hasSelect && !$hasTypeAttribute) { foreach ($output['attributes'] as &$attribute) { unset($attribute['type']); } From 7e185cd7991490c837825c79384038b1e12d4b43 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 8 Aug 2023 03:34:13 +0530 Subject: [PATCH 15/27] moved formatting logic to relationship attribute model --- app/controllers/api/databases.php | 14 ------------- .../Response/Model/AttributeRelationship.php | 21 ++++++++++++++++++- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 9279d4d115..424d162f6f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1718,20 +1718,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $filterQueries = Query::groupByType($queries)['filters']; $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); - //Add relationship data from options to attributes as it loses options during response setup - foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $attribute->getAttribute('options'); - if (!\is_null($options)) { - $attribute->setAttribute('relatedCollection', $options['relatedCollection']); - $attribute->setAttribute('relationType', $options['relationType']); - $attribute->setAttribute('twoWay', $options['twoWay']); - $attribute->setAttribute('twoWayKey', $options['twoWayKey']); - $attribute->setAttribute('side', $options['side']); - $attribute->setAttribute('onDelete', $options['onDelete']); - } - } - } $output = $response->output(new Document([ 'total' => $total, 'attributes' => $attributes, diff --git a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php index dc3300c098..b6013e8ae1 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php @@ -3,7 +3,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; - +use Utopia\Database\Document; class AttributeRelationship extends Attribute { public function __construct() @@ -73,4 +73,23 @@ class AttributeRelationship extends Attribute { return Response::MODEL_ATTRIBUTE_RELATIONSHIP; } + + /** + * Process Document before returning it to the client + * + * @return Document + */ + public function filter(Document $document): Document + { + $options = $document->getAttribute('options'); + if (!\is_null($options)) { + $document->setAttribute('relatedCollection', $options['relatedCollection']); + $document->setAttribute('relationType', $options['relationType']); + $document->setAttribute('twoWay', $options['twoWay']); + $document->setAttribute('twoWayKey', $options['twoWayKey']); + $document->setAttribute('side', $options['side']); + $document->setAttribute('onDelete', $options['onDelete']); + } + return $document; + } } From 769114d1616252e6a16b44be1f7d0bec19959168 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Tue, 8 Aug 2023 03:35:13 +0530 Subject: [PATCH 16/27] lint fix --- src/Appwrite/Utopia/Response/Model/AttributeRelationship.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php index b6013e8ae1..d88fbd1530 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeRelationship.php @@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Utopia\Database\Document; + class AttributeRelationship extends Attribute { public function __construct() From 51ceb5d74a504f74a1d946056568fcfd4b241434 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 9 Aug 2023 00:12:53 +0530 Subject: [PATCH 17/27] prohibit select queries in list attributes and remove static method --- app/controllers/api/databases.php | 33 ++----------------- .../Database/Validator/Queries/Attributes.php | 8 ++++- .../Database/Validator/Queries/Base.php | 11 ++++++- src/Appwrite/Utopia/Response.php | 27 --------------- 4 files changed, 20 insertions(+), 59 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 424d162f6f..baad060c19 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1678,22 +1678,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $queries = Query::parseQueries($queries); - // Add type property in query if select query exists and type property doesn't exist as type is required for response model - $hasSelect = false; - $hasTypeAttribute = false; - foreach ($queries as $query) { - if ($query->getMethod() === Query::TYPE_SELECT) { - $hasSelect = true; - } - if (\array_search('type', $query->getValues())) { - $hasTypeAttribute = true; - } - } - - if ($hasSelect && !$hasTypeAttribute) { - \array_push($queries, Query::select(['type'])); - } - \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); // Get cursor document if there was a cursor query @@ -1714,23 +1698,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $cursor->setValue($cursorDocument[0]); } - $attributes = $dbForProject->find('attributes', $queries); $filterQueries = Query::groupByType($queries)['filters']; - $total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT); - $output = $response->output(new Document([ - 'total' => $total, - 'attributes' => $attributes, + $response->dynamic(new Document([ + 'total' => $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT), + 'attributes' => $dbForProject->find('attributes', $queries), ]), Response::MODEL_ATTRIBUTE_LIST); - - // If type Attribute didn't exist in select query we need to remove type attribute from attribute list - if ($hasSelect && !$hasTypeAttribute) { - foreach ($output['attributes'] as &$attribute) { - unset($attribute['type']); - } - } - - $response->static($output); }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 4a35c82b73..8a1a95b7f7 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -2,6 +2,8 @@ namespace Appwrite\Utopia\Database\Validator\Queries; +use Utopia\Database\Validator\Query\Select; + class Attributes extends Base { public const ALLOWED_ATTRIBUTES = [ @@ -14,12 +16,16 @@ class Attributes extends Base 'error' ]; + public const PROHIBITED_QUERIES = [ + Select::class + ]; + /** * Expression constructor * */ public function __construct() { - parent::__construct('attributes', self::ALLOWED_ATTRIBUTES); + parent::__construct('attributes', self::ALLOWED_ATTRIBUTES, self::PROHIBITED_QUERIES); } } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 587862fa65..2425954c1e 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -2,6 +2,7 @@ namespace Appwrite\Utopia\Database\Validator\Queries; +use Appwrite\Extend\Exception; use Utopia\Database\Validator\Queries; use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; @@ -22,7 +23,7 @@ class Base extends Queries * @param string[] $allowedAttributes * @throws \Exception */ - public function __construct(string $collection, array $allowedAttributes) + public function __construct(string $collection, array $allowedAttributes, ?array $prohibitedQueries = []) { $collection = Config::getParam('collections', [])[$collection]; // array for constant lookup time @@ -69,6 +70,14 @@ class Base extends Queries new Order($attributes), new Select($attributes), ]; + // Remove prohibited validators from the $validators array + foreach ($prohibitedQueries as $prohibitedQuery) { + foreach ($validators as $key => $validator) { + if ($validator instanceof $prohibitedQuery) { + unset($validators[$key]); + } + } + } parent::__construct($validators); } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 964d93ae1e..bae5b3cca9 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -458,33 +458,6 @@ class Response extends SwooleResponse } } - /** - * Sends the response based on content type - * - * @param array $ouput - * - * return void - * @throws Exception - */ - public function static(array $output): void - { - switch ($this->getContentType()) { - case self::CONTENT_TYPE_JSON: - $this->json(!empty($output) ? $output : new \stdClass()); - break; - - case self::CONTENT_TYPE_YAML: - $this->yaml(!empty($output) ? $output : new \stdClass()); - break; - - case self::CONTENT_TYPE_NULL: - break; - - default: - $this->json(!empty($output) ? $output : new \stdClass()); - } - } - /** * Generate valid response object from document data * From 11df973aa16bf6ea4f90633b16d5a1f0f1b0ff5c Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 9 Aug 2023 02:39:04 +0530 Subject: [PATCH 18/27] review changes --- src/Appwrite/GraphQL/Types/Mapper.php | 2 ++ src/Appwrite/Utopia/Database/Validator/Queries/Base.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index 9d2705baa7..0be60d93dc 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -252,6 +252,8 @@ class Mapper case 'Appwrite\Utopia\Database\Validator\Queries\Base': case 'Appwrite\Utopia\Database\Validator\Queries\Buckets': case 'Appwrite\Utopia\Database\Validator\Queries\Collections': + case 'Appwrite\Utopia\Database\Validator\Queries\Attributes': + case 'Appwrite\Utopia\Database\Validator\Queries\Indexes': case 'Appwrite\Utopia\Database\Validator\Queries\Databases': case 'Appwrite\Utopia\Database\Validator\Queries\Deployments': case 'Utopia\Database\Validator\Queries\Documents': diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 2425954c1e..5a822ab533 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -23,7 +23,7 @@ class Base extends Queries * @param string[] $allowedAttributes * @throws \Exception */ - public function __construct(string $collection, array $allowedAttributes, ?array $prohibitedQueries = []) + public function __construct(string $collection, array $allowedAttributes, array $prohibitedQueries = []) { $collection = Config::getParam('collections', [])[$collection]; // array for constant lookup time From f6d7449dd58e7c96266d079836d3f5bd1f2a948b Mon Sep 17 00:00:00 2001 From: prateek banga Date: Wed, 9 Aug 2023 14:19:47 +0530 Subject: [PATCH 19/27] remove select queries and prohibit queries from Base validator --- .../Utopia/Database/Validator/Queries/Attributes.php | 2 +- .../Utopia/Database/Validator/Queries/Base.php | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 8a1a95b7f7..893f51e22b 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -26,6 +26,6 @@ class Attributes extends Base */ public function __construct() { - parent::__construct('attributes', self::ALLOWED_ATTRIBUTES, self::PROHIBITED_QUERIES); + parent::__construct('attributes', self::ALLOWED_ATTRIBUTES); } } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index bf73795b80..3eea7b7b7e 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -9,7 +9,6 @@ use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\Query\Filter; use Utopia\Database\Validator\Query\Order; -use Utopia\Database\Validator\Query\Select; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; @@ -23,7 +22,7 @@ class Base extends Queries * @param string[] $allowedAttributes * @throws \Exception */ - public function __construct(string $collection, array $allowedAttributes, array $prohibitedQueries = []) + public function __construct(string $collection, array $allowedAttributes) { $config = Config::getParam('collections', []); $collections = array_merge($config['console'], $config['projects'], $config['buckets'], $config['databases']); @@ -70,16 +69,7 @@ class Base extends Queries new Cursor(), new Filter($attributes), new Order($attributes), - new Select($attributes), ]; - // Remove prohibited validators from the $validators array - foreach ($prohibitedQueries as $prohibitedQuery) { - foreach ($validators as $key => $validator) { - if ($validator instanceof $prohibitedQuery) { - unset($validators[$key]); - } - } - } parent::__construct($validators); } From 185d09d764f2d688b19f8de6488a666022c84479 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 10 Aug 2023 00:11:18 +0530 Subject: [PATCH 20/27] adds more queries in tests, upgrade db library --- composer.json | 6 +-- composer.lock | 42 +++++++++---------- .../e2e/Services/Databases/DatabasesBase.php | 36 ++++++++++++---- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/composer.json b/composer.json index 9be851f2fa..b6ff28d89e 100644 --- a/composer.json +++ b/composer.json @@ -43,13 +43,13 @@ "ext-sockets": "*", "appwrite/php-clamav": "2.0.*", "appwrite/php-runtimes": "0.11.*", - "utopia-php/abuse": "0.29.*", + "utopia-php/abuse": "0.30.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.31.*", + "utopia-php/audit": "0.32.*", "utopia-php/cache": "0.8.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.40.*", + "utopia-php/database": "0.41.*", "utopia-php/domains": "1.1.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.28.*", diff --git a/composer.lock b/composer.lock index 998762ee30..dfb3d9e859 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": "b9dd376db262a8457dc9c25c422aa705", + "content-hash": "8068408e6b0e275fb7887c956b918d03", "packages": [ { "name": "adhocore/jwt", @@ -1225,23 +1225,23 @@ }, { "name": "utopia-php/abuse", - "version": "0.29.0", + "version": "0.30.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "7589d0c7a6f685fcbb02d57875f034bd233ec262" + "reference": "9ba1b9ca96386aedfb5be23d739433652124e00f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/7589d0c7a6f685fcbb02d57875f034bd233ec262", - "reference": "7589d0c7a6f685fcbb02d57875f034bd233ec262", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/9ba1b9ca96386aedfb5be23d739433652124e00f", + "reference": "9ba1b9ca96386aedfb5be23d739433652124e00f", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.40.*" + "utopia-php/database": "0.41.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1268,9 +1268,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.29.0" + "source": "https://github.com/utopia-php/abuse/tree/0.30.0" }, - "time": "2023-08-03T08:22:12+00:00" + "time": "2023-08-09T17:34:55+00:00" }, { "name": "utopia-php/analytics", @@ -1320,21 +1320,21 @@ }, { "name": "utopia-php/audit", - "version": "0.31.0", + "version": "0.32.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "f1b0165fccb6ec665f7ae947bfed56a8f6b877cb" + "reference": "db769bcbc3bc4a187e3be97f5e532311ad8fae27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/f1b0165fccb6ec665f7ae947bfed56a8f6b877cb", - "reference": "f1b0165fccb6ec665f7ae947bfed56a8f6b877cb", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/db769bcbc3bc4a187e3be97f5e532311ad8fae27", + "reference": "db769bcbc3bc4a187e3be97f5e532311ad8fae27", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.40.*" + "utopia-php/database": "0.41.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1361,9 +1361,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.31.0" + "source": "https://github.com/utopia-php/audit/tree/0.32.0" }, - "time": "2023-08-03T08:22:32+00:00" + "time": "2023-08-09T17:34:57+00:00" }, { "name": "utopia-php/cache", @@ -1516,16 +1516,16 @@ }, { "name": "utopia-php/database", - "version": "0.40.0", + "version": "0.41.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "ec586ba1c5fc83856df4feaa05464da72b72ee0d" + "reference": "98dc6a94e636fe8f955c20fa4833db8986b5c27a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/ec586ba1c5fc83856df4feaa05464da72b72ee0d", - "reference": "ec586ba1c5fc83856df4feaa05464da72b72ee0d", + "url": "https://api.github.com/repos/utopia-php/database/zipball/98dc6a94e636fe8f955c20fa4833db8986b5c27a", + "reference": "98dc6a94e636fe8f955c20fa4833db8986b5c27a", "shasum": "" }, "require": { @@ -1566,9 +1566,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.40.0" + "source": "https://github.com/utopia-php/database/tree/0.41.0" }, - "time": "2023-08-03T08:01:37+00:00" + "time": "2023-08-09T02:52:31+00:00" }, { "name": "utopia-php/domains", diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index ffba8a63e6..babb8667ed 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -5,10 +5,12 @@ namespace Tests\E2E\Services\Databases; use Appwrite\Extend\Exception; use Tests\E2E\Client; use Utopia\Database\Database; +use Utopia\Database\Document; use Utopia\Database\DateTime; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; trait DatabasesBase @@ -322,15 +324,24 @@ trait DatabasesBase public function testListAttributes(array $data): void { $databaseId = $data['databaseId']; - $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'queries' => ['equal("type", "string")'], + 'queries' => ['equal("type", "string")', 'limit(2)', 'cursorAfter(title)'], ]); - $this->assertEquals(200, $attributes['headers']['status-code']); - $this->assertEquals(4, $attributes['body']['total']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, \count($response['body']['attributes'])); + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => ['select(key)'], + ]); + $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); + $this->assertEquals(400, $response['headers']['status-code']); } /** @@ -1070,15 +1081,24 @@ trait DatabasesBase public function testListIndexes(array $data): void { $databaseId = $data['databaseId']; - $indexes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'queries' => ['equal("type", "key")'], + 'queries' => ['equal("type", "key")', 'limit(2)'], ]); - $this->assertEquals(200, $indexes['headers']['status-code']); - $this->assertEquals(3, $indexes['body']['total']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(2, \count($response['body']['indexes'])); + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => ['select(key)'], + ]); + $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); + $this->assertEquals(400, $response['headers']['status-code']); } /** From 02d4b6b6123050a7796b273c53998e8bdaa51af6 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 10 Aug 2023 15:14:23 +0530 Subject: [PATCH 21/27] fix test case by adding internal attributes --- tests/e2e/Services/Databases/DatabasesBase.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index babb8667ed..1ac3d9305e 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1378,7 +1378,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - 'select(["title", "releaseYear"])', + 'select(["title", "releaseYear", "$id"])', ], ]); @@ -4098,10 +4098,9 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - 'select(["libraries.*"])', + 'select(["libraries.*", "$id"])', ], ]); - $document = $response['body']['documents'][0]; $this->assertEquals(200, $response['headers']['status-code']); $this->assertArrayHasKey('libraries', $document); @@ -4111,7 +4110,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - 'select(["fullName"])' + 'select(["fullName", "$id"])' ], ]); From 023e88ff5649b04bfb5d31a31c0ddf995ef80184 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 10 Aug 2023 20:00:13 +0530 Subject: [PATCH 22/27] removes condition --- src/Appwrite/Utopia/Response.php | 58 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 44642b3615..568a551e1f 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -493,43 +493,41 @@ class Response extends SwooleResponse } } - if ($data->isSet($key)) { - if ($rule['array']) { - if (!is_array($document[$key])) { - throw new Exception($key . ' must be an array of type ' . $rule['type']); - } + if ($rule['array']) { + if (!is_array($document[$key])) { + throw new Exception($key . ' must be an array of type ' . $rule['type']); + } - foreach ($document[$key] as $index => $item) { - if ($item instanceof Document) { - if (\is_array($rule['type'])) { - foreach ($rule['type'] as $type) { - $condition = false; - foreach ($this->getModel($type)->conditions as $attribute => $val) { - $condition = $item->getAttribute($attribute) === $val; - if (!$condition) { - break; - } - } - if ($condition) { - $ruleType = $type; + foreach ($document[$key] as $index => $item) { + if ($item instanceof Document) { + if (\is_array($rule['type'])) { + foreach ($rule['type'] as $type) { + $condition = false; + foreach ($this->getModel($type)->conditions as $attribute => $val) { + $condition = $item->getAttribute($attribute) === $val; + if (!$condition) { break; } } - } else { - $ruleType = $rule['type']; + if ($condition) { + $ruleType = $type; + break; + } } - - if (!array_key_exists($ruleType, $this->models)) { - throw new Exception('Missing model for rule: ' . $ruleType); - } - - $data[$key][$index] = $this->output($item, $ruleType); + } else { + $ruleType = $rule['type']; } + + if (!array_key_exists($ruleType, $this->models)) { + throw new Exception('Missing model for rule: ' . $ruleType); + } + + $data[$key][$index] = $this->output($item, $ruleType); } - } else { - if ($document[$key] instanceof Document) { - $data[$key] = $this->output($data[$key], $rule['type']); - } + } + } else { + if ($document[$key] instanceof Document) { + $data[$key] = $this->output($data[$key], $rule['type']); } } $output[$key] = $data[$key]; From 233f4ebb562dce9193f22d8dc792fec73608de6f Mon Sep 17 00:00:00 2001 From: prateek banga Date: Thu, 10 Aug 2023 20:03:47 +0530 Subject: [PATCH 23/27] lint fix --- src/Appwrite/Utopia/Response.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 568a551e1f..63e9170008 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -530,6 +530,7 @@ class Response extends SwooleResponse $data[$key] = $this->output($data[$key], $rule['type']); } } + $output[$key] = $data[$key]; } From a8897e6b6ff4fd0ba6970557c5abebc783a63f47 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 10 Aug 2023 21:33:40 -0400 Subject: [PATCH 24/27] Update libs --- composer.json | 6 +++--- composer.lock | 42 +++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/composer.json b/composer.json index b6ff28d89e..1edb6d0e1c 100644 --- a/composer.json +++ b/composer.json @@ -43,13 +43,13 @@ "ext-sockets": "*", "appwrite/php-clamav": "2.0.*", "appwrite/php-runtimes": "0.11.*", - "utopia-php/abuse": "0.30.*", + "utopia-php/abuse": "0.31.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.32.*", + "utopia-php/audit": "0.33.*", "utopia-php/cache": "0.8.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.41.*", + "utopia-php/database": "0.42.*", "utopia-php/domains": "1.1.*", "utopia-php/dsn": "0.1.*", "utopia-php/framework": "0.28.*", diff --git a/composer.lock b/composer.lock index dfb3d9e859..4a0862679d 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": "8068408e6b0e275fb7887c956b918d03", + "content-hash": "2098172fc4b71eb0d41dcdbfea2f5061", "packages": [ { "name": "adhocore/jwt", @@ -1225,23 +1225,23 @@ }, { "name": "utopia-php/abuse", - "version": "0.30.0", + "version": "0.31.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "9ba1b9ca96386aedfb5be23d739433652124e00f" + "reference": "d771c2c8d7d1237b1d04b5bf57b07a9b4736e627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/9ba1b9ca96386aedfb5be23d739433652124e00f", - "reference": "9ba1b9ca96386aedfb5be23d739433652124e00f", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/d771c2c8d7d1237b1d04b5bf57b07a9b4736e627", + "reference": "d771c2c8d7d1237b1d04b5bf57b07a9b4736e627", "shasum": "" }, "require": { "ext-curl": "*", "ext-pdo": "*", "php": ">=8.0", - "utopia-php/database": "0.41.*" + "utopia-php/database": "0.42.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1268,9 +1268,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.30.0" + "source": "https://github.com/utopia-php/abuse/tree/0.31.0" }, - "time": "2023-08-09T17:34:55+00:00" + "time": "2023-08-11T01:17:15+00:00" }, { "name": "utopia-php/analytics", @@ -1320,21 +1320,21 @@ }, { "name": "utopia-php/audit", - "version": "0.32.0", + "version": "0.33.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "db769bcbc3bc4a187e3be97f5e532311ad8fae27" + "reference": "6fb82331c58c66cbdb8a419314a687fcb18a1d22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/db769bcbc3bc4a187e3be97f5e532311ad8fae27", - "reference": "db769bcbc3bc4a187e3be97f5e532311ad8fae27", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/6fb82331c58c66cbdb8a419314a687fcb18a1d22", + "reference": "6fb82331c58c66cbdb8a419314a687fcb18a1d22", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.41.*" + "utopia-php/database": "0.42.*" }, "require-dev": { "laravel/pint": "1.5.*", @@ -1361,9 +1361,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.32.0" + "source": "https://github.com/utopia-php/audit/tree/0.33.0" }, - "time": "2023-08-09T17:34:57+00:00" + "time": "2023-08-11T01:17:28+00:00" }, { "name": "utopia-php/cache", @@ -1516,16 +1516,16 @@ }, { "name": "utopia-php/database", - "version": "0.41.0", + "version": "0.42.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "98dc6a94e636fe8f955c20fa4833db8986b5c27a" + "reference": "5631f151ce2b454517f11c1914e50a1fa70c7bd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/98dc6a94e636fe8f955c20fa4833db8986b5c27a", - "reference": "98dc6a94e636fe8f955c20fa4833db8986b5c27a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/5631f151ce2b454517f11c1914e50a1fa70c7bd1", + "reference": "5631f151ce2b454517f11c1914e50a1fa70c7bd1", "shasum": "" }, "require": { @@ -1566,9 +1566,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.41.0" + "source": "https://github.com/utopia-php/database/tree/0.42.0" }, - "time": "2023-08-09T02:52:31+00:00" + "time": "2023-08-10T23:18:38+00:00" }, { "name": "utopia-php/domains", From 6ef7416fffb64f2bec14ff8d485b0deaa1391021 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 11 Aug 2023 15:47:33 +0530 Subject: [PATCH 25/27] fixes debugger usage --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 25781932f1..7b37f9fed7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,7 +84,7 @@ services: - ./docs:/usr/src/code/docs - ./public:/usr/src/code/public - ./src:/usr/src/code/src - - ./dev:/usr/local/dev + - ./dev:/usr/src/code/dev depends_on: - mariadb - redis From 0304adf872dde7457172bb48e04e303c6cd4b580 Mon Sep 17 00:00:00 2001 From: prateek banga Date: Fri, 11 Aug 2023 16:19:05 +0530 Subject: [PATCH 26/27] fix test cases --- app/init.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/init.php b/app/init.php index 2e59869993..1b74b81bc4 100644 --- a/app/init.php +++ b/app/init.php @@ -947,7 +947,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons if (APP_MODE_ADMIN !== $mode) { if ($project->isEmpty()) { - $user = new Document(['$id' => ID::custom(''), '$collection' => 'users']); + $user = new Document([]); } else { $user = $dbForProject->getDocument('users', Auth::$unique); } @@ -959,14 +959,14 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons $user->isEmpty() // Check a document has been found in the DB || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration) ) { // Validate user has valid login token - $user = new Document(['$id' => ID::custom(''), '$collection' => 'users']); + $user = new Document([]); } if (APP_MODE_ADMIN === $mode) { if ($user->find('teamId', $project->getAttribute('teamId'), 'memberships')) { Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. } else { - $user = new Document(['$id' => ID::custom(''), '$collection' => 'users']); + $user = new Document([]); } } @@ -989,7 +989,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons } if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token - $user = new Document(['$id' => ID::custom(''), '$collection' => 'users']); + $user = new Document([]); } } From 7cd995ac3c57a3006520152b64ba458f9d40d01b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 11 Aug 2023 12:29:55 -0400 Subject: [PATCH 27/27] Apply suggestions from code review --- src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php | 4 ---- tests/e2e/Services/Databases/DatabasesBase.php | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php index 893f51e22b..1463316ad1 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -16,10 +16,6 @@ class Attributes extends Base 'error' ]; - public const PROHIBITED_QUERIES = [ - Select::class - ]; - /** * Expression constructor * diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 1ac3d9305e..c2c1c70bd6 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -338,7 +338,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'queries' => ['select(key)'], + 'queries' => ['select(["key"])'], ]); $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); $this->assertEquals(400, $response['headers']['status-code']); @@ -1095,7 +1095,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'queries' => ['select(key)'], + 'queries' => ['select(["key"])'], ]); $this->assertEquals(Exception::GENERAL_ARGUMENT_INVALID, $response['body']['type']); $this->assertEquals(400, $response['headers']['status-code']);