From 3229956eefd3eba10b721cd476fbbed706fc434d Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 19 Oct 2025 13:16:39 +0300 Subject: [PATCH 01/20] Enhance XList actions to include 'includeTotal' parameter for total count control --- .../Http/Databases/Collections/Attributes/XList.php | 6 ++++-- .../Http/Databases/Collections/Documents/XList.php | 10 ++++++---- .../Http/Databases/Collections/Indexes/XList.php | 6 ++++-- .../Databases/Http/Databases/Collections/XList.php | 6 ++++-- .../Modules/Databases/Http/Databases/XList.php | 6 ++++-- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 6daa180df9..1c340551d4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -18,6 +18,7 @@ use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\Boolean; class XList extends Action { @@ -60,12 +61,13 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->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) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { @@ -122,7 +124,7 @@ class XList extends Action try { $attributes = $dbForProject->find('attributes', $queries); - $total = $dbForProject->count('attributes', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('attributes', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; $attribute = $this->isCollectionsAPI() ? 'attribute' : 'column'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index a30fed47ed..719d6e6b7d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -23,6 +23,7 @@ use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Action { @@ -67,6 +68,7 @@ class XList extends Action ->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 ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') @@ -74,7 +76,7 @@ class XList extends Action ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void + public function action(string $databaseId, string $collectionId, array $queries, ?string $transactionId, bool $includeTotal, UtopiaResponse $response, Database $dbForProject, StatsUsage $queueForStatsUsage, TransactionState $transactionState): void { $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -129,16 +131,16 @@ class XList extends Action // Use transaction-aware document retrieval if transactionId is provided if ($transactionId !== null) { $documents = $transactionState->listDocuments($collectionTableId, $transactionId, $queries); - $total = $transactionState->countDocuments($collectionTableId, $transactionId, $queries); + $total = $includeTotal ? $transactionState->countDocuments($collectionTableId, $transactionId, $queries) : 0; } elseif (! empty($selectQueries)) { // has selects, allow relationship on documents $documents = $dbForProject->find($collectionTableId, $queries); - $total = $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0; } else { // has no selects, disable relationship loading on documents /* @type Document[] $documents */ $documents = $dbForProject->skipRelationships(fn () => $dbForProject->find($collectionTableId, $queries)); - $total = $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0; } } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 60e52f883a..750d1e5bc4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -19,6 +19,7 @@ use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\Boolean; class XList extends Action { @@ -62,12 +63,13 @@ class XList extends Action ->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) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(string $databaseId, string $collectionId, array $queries, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, string $collectionId, array $queries, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { /** @var Document $database */ $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -125,7 +127,7 @@ class XList extends Action } try { - $total = $dbForProject->count('indexes', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('indexes', $queries, APP_LIMIT_COUNT) : 0; $indexes = $dbForProject->find('indexes', $queries); } catch (OrderException $e) { $documents = $this->isCollectionsAPI() ? 'documents' : 'rows'; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index b4cc5470d9..1751e0c1ef 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -20,6 +20,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Action { @@ -63,12 +64,13 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(string $databaseId, array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void + public function action(string $databaseId, array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -112,7 +114,7 @@ class XList extends Action try { $collections = $dbForProject->find('database_' . $database->getSequence(), $queries); - $total = $dbForProject->count('database_' . $database->getSequence(), $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('database_' . $database->getSequence(), $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL); } catch (QueryException) { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index d7c6245e5c..3e705dc954 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -19,6 +19,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Action { @@ -58,12 +59,13 @@ class XList extends Action ]) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(array $queries, string $search, UtopiaResponse $response, Database $dbForProject): void + public function action(array $queries, string $search, bool $includeTotal, UtopiaResponse $response, Database $dbForProject): void { $queries = Query::parseQueries($queries); @@ -98,7 +100,7 @@ class XList extends Action try { $databases = $dbForProject->find('databases', $queries); - $total = $dbForProject->count('databases', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('databases', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order column '{$e->getAttribute()}' had a null value. Cursor pagination requires all rows order column values are non-null."); } catch (QueryException) { From 7bbe08f23e25115c62c43ea4ea7d54eaad77eaa0 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 19 Oct 2025 14:38:32 +0300 Subject: [PATCH 02/20] Enhance XList classes to support 'includeTotal' parameter for controlling total count in database queries --- .../Modules/Databases/Http/TablesDB/Tables/Columns/XList.php | 2 ++ .../Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php | 2 ++ .../Modules/Databases/Http/TablesDB/Tables/Rows/XList.php | 2 ++ .../Platform/Modules/Databases/Http/TablesDB/Tables/XList.php | 2 ++ src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php | 2 ++ 5 files changed, 10 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 13bf3257e3..1476f73c4e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -10,6 +10,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Columns; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\Boolean; class XList extends AttributesXList { @@ -48,6 +49,7 @@ class XList extends AttributesXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') ->param('queries', [], new Columns(), '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 columns: ' . implode(', ', Columns::ALLOWED_COLUMNS), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index 041b4aa70c..a73e18b7b4 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -11,6 +11,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Indexes; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; +use Utopia\Validator\Boolean; class XList extends IndexXList { @@ -50,6 +51,7 @@ class XList extends IndexXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->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 columns: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 8c96997ea5..21762883f7 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -12,6 +12,7 @@ use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends DocumentXList { @@ -52,6 +53,7 @@ class XList extends DocumentXList ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the TablesDB service [server integration](https://appwrite.io/docs/products/databases/tables#create-table).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index a47a972371..52c2cc3170 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -12,6 +12,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends CollectionXList { @@ -51,6 +52,7 @@ class XList extends CollectionXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Tables(), '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 columns: ' . implode(', ', Tables::ALLOWED_COLUMNS), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php index 4d28834d31..3ce4eba98b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php @@ -11,6 +11,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Databases; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends DatabaseXList { @@ -44,6 +45,7 @@ class XList extends DatabaseXList )) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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 columns: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); From f16de4abb9ffdf355111dba8e4f73389fc3ae44e Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 19 Oct 2025 14:46:55 +0300 Subject: [PATCH 03/20] Refactor XList classes to consistently implement 'includeTotal' parameter for total count control in database queries --- .../Platform/Modules/Functions/Http/Deployments/XList.php | 5 ++++- .../Platform/Modules/Functions/Http/Executions/XList.php | 5 ++++- .../Platform/Modules/Functions/Http/Functions/XList.php | 5 ++++- .../Platform/Modules/Projects/Http/Projects/XList.php | 6 ++++-- src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php | 5 ++++- .../Platform/Modules/Sites/Http/Deployments/XList.php | 5 ++++- src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php | 6 ++++-- src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php | 6 ++++-- .../Modules/Tokens/Http/Tokens/Buckets/Files/XList.php | 6 ++++-- 9 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 2850c5b279..acf171773b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -20,6 +20,7 @@ use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Base { @@ -57,6 +58,7 @@ class XList extends Base ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') @@ -67,6 +69,7 @@ class XList extends Base string $functionId, array $queries, string $search, + bool $includeTotal, Request $request, Response $response, Database $dbForProject @@ -120,7 +123,7 @@ class XList extends Base try { $results = $dbForProject->find('deployments', $queries); - $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 46a41e6517..dac3697265 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -20,6 +20,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; class XList extends Base { @@ -56,6 +57,7 @@ class XList extends Base )) ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Executions::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); @@ -64,6 +66,7 @@ class XList extends Base public function action( string $functionId, array $queries, + bool $includeTotal, Response $response, Database $dbForProject ) { @@ -115,7 +118,7 @@ class XList extends Base try { $results = $dbForProject->find('executions', $queries); - $total = $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php index 4b03a5b6cc..d73a3dae97 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -18,6 +18,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Base { @@ -54,6 +55,7 @@ class XList extends Base )) ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Functions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); @@ -62,6 +64,7 @@ class XList extends Base public function action( array $queries, string $search, + bool $includeTotal, Response $response, Database $dbForProject ) { @@ -104,7 +107,7 @@ class XList extends Base try { $functions = $dbForProject->find('functions', $queries); - $total = $dbForProject->count('functions', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('functions', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php index 3d06103e75..51a36ccb03 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php @@ -19,6 +19,7 @@ use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Action { @@ -59,12 +60,13 @@ class XList extends Action )) ->param('queries', [], $this->getQueriesValidator(), '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(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->callback($this->action(...)); } - public function action(array $queries, string $search, Response $response, Database $dbForPlatform) + public function action(array $queries, string $search, bool $includeTotal, Response $response, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); @@ -104,7 +106,7 @@ class XList extends Action $filterQueries = Query::groupByType($queries)['filters']; try { $projects = $dbForPlatform->find('projects', $queries); - $total = $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (Order $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php index e084cf76b2..7f953cb70b 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php @@ -16,6 +16,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Action { @@ -51,6 +52,7 @@ class XList extends Action )) ->param('queries', [], new Rules(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Rules::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForPlatform') @@ -60,6 +62,7 @@ class XList extends Action public function action( array $queries, string $search, + bool $includeTotal, Response $response, Document $project, Database $dbForPlatform @@ -112,7 +115,7 @@ class XList extends Action $response->dynamic(new Document([ 'rules' => $rules, - 'total' => $dbForPlatform->count('rules', $filterQueries, APP_LIMIT_COUNT), + 'total' => $includeTotal ? $dbForPlatform->count('rules', $filterQueries, APP_LIMIT_COUNT) : 0, ]), Response::MODEL_PROXY_RULE_LIST); } } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index 436cd69b52..cb82ad4cb9 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -20,6 +20,7 @@ use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Base { @@ -57,6 +58,7 @@ class XList extends Base ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') @@ -67,6 +69,7 @@ class XList extends Base string $siteId, array $queries, string $search, + bool $includeTotal, Request $request, Response $response, Database $dbForProject @@ -120,7 +123,7 @@ class XList extends Base try { $results = $dbForProject->find('deployments', $queries); - $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index f9bee3e425..05d03af0ff 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -19,6 +19,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; class XList extends Base { @@ -55,12 +56,13 @@ class XList extends Base )) ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Logs(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(string $siteId, array $queries, Response $response, Database $dbForProject) + public function action(string $siteId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { $site = $dbForProject->getDocument('sites', $siteId); @@ -107,7 +109,7 @@ class XList extends Base try { $results = $dbForProject->find('executions', $queries); - $total = $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php index 988a2d2e20..31957a3094 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -18,6 +18,7 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; class XList extends Base { @@ -54,12 +55,13 @@ class XList extends Base )) ->param('queries', [], new Sites(), '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(', ', Sites::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(array $queries, string $search, Response $response, Database $dbForProject) + public function action(array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -100,7 +102,7 @@ class XList extends Base try { $sites = $dbForProject->find('sites', $queries); - $total = $dbForProject->count('sites', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('sites', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 231164d6ee..68e03160bb 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -15,6 +15,7 @@ use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\UID; use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; class XList extends Action { @@ -53,12 +54,13 @@ class XList extends Action ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') ->param('queries', [], new FileTokens(), '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(', ', FileTokens::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); } - public function action(string $bucketId, string $fileId, array $queries, Response $response, Database $dbForProject) + public function action(string $bucketId, string $fileId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { ['bucket' => $bucket, 'file' => $file] = $this->getFileAndBucket($dbForProject, $bucketId, $fileId); @@ -86,7 +88,7 @@ class XList extends Action $response->dynamic(new Document([ 'tokens' => $dbForProject->find('resourceTokens', $queries), - 'total' => $dbForProject->count('resourceTokens', $filterQueries, APP_LIMIT_COUNT), + 'total' => $includeTotal ? $dbForProject->count('resourceTokens', $filterQueries, APP_LIMIT_COUNT) : 0, ]), Response::MODEL_RESOURCE_TOKEN_LIST); } } From d0e0f67fee8377ae57cdf20cc446d45f86b06fed Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 19 Oct 2025 15:45:16 +0300 Subject: [PATCH 04/20] Implement 'includeTotal' parameter across various API endpoints to control total count in responses --- app/controllers/api/account.php | 5 +++-- app/controllers/api/messaging.php | 20 ++++++++++++-------- app/controllers/api/migrations.php | 5 +++-- app/controllers/api/projects.php | 15 +++++++++------ app/controllers/api/storage.php | 12 +++++++----- app/controllers/api/teams.php | 13 ++++++++----- app/controllers/api/users.php | 17 ++++++++++------- app/controllers/api/vcs.php | 5 +++-- 8 files changed, 55 insertions(+), 37 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 418770fc9c..369df5c7b9 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -5304,10 +5304,11 @@ App::get('/v1/account/identities') contentType: ContentType::JSON )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('dbForProject') - ->action(function (array $queries, Response $response, Document $user, Database $dbForProject) { + ->action(function (array $queries, bool $includeTotal, Response $response, Document $user, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -5348,7 +5349,7 @@ App::get('/v1/account/identities') } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $total = $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; $response->dynamic(new Document([ 'identities' => $results, diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index dbc384f3c4..bba2cb78e7 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -985,9 +985,10 @@ App::get('/v1/messaging/providers') )) ->param('queries', [], new Providers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1023,7 +1024,7 @@ App::get('/v1/messaging/providers') } try { $providers = $dbForProject->find('providers', $queries); - $total = $dbForProject->count('providers', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('providers', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } @@ -2292,9 +2293,10 @@ App::get('/v1/messaging/topics') )) ->param('queries', [], new Topics(), '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(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2330,7 +2332,7 @@ App::get('/v1/messaging/topics') } try { $topics = $dbForProject->find('topics', $queries); - $total = $dbForProject->count('topics', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('topics', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } @@ -3511,9 +3513,10 @@ App::get('/v1/messaging/messages') )) ->param('queries', [], new Messages(), '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(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') - ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -3549,7 +3552,7 @@ App::get('/v1/messaging/messages') } try { $messages = $dbForProject->find('messages', $queries); - $total = $dbForProject->count('messages', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('messages', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } @@ -3677,9 +3680,10 @@ App::get('/v1/messaging/messages/:messageId/targets') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $messageId, array $queries, Response $response, Database $dbForProject) { + ->action(function (string $messageId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3729,7 +3733,7 @@ App::get('/v1/messaging/messages/:messageId/targets') } try { $targets = $dbForProject->find('targets', $queries); - $total = $dbForProject->count('targets', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('targets', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 4a968e63f2..f050ea2f15 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -460,9 +460,10 @@ App::get('/v1/migrations') )) ->param('queries', [], new Migrations(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Migrations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -501,7 +502,7 @@ App::get('/v1/migrations') $filterQueries = Query::groupByType($queries)['filters']; try { $migrations = $dbForProject->find('migrations', $queries); - $total = $dbForProject->count('migrations', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('migrations', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 1d68377d8c..1be73f598f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1233,9 +1233,10 @@ App::get('/v1/projects/:projectId/webhooks') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') - ->action(function (string $projectId, Response $response, Database $dbForPlatform) { + ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { $project = $dbForPlatform->getDocument('projects', $projectId); @@ -1250,7 +1251,7 @@ App::get('/v1/projects/:projectId/webhooks') $response->dynamic(new Document([ 'webhooks' => $webhooks, - 'total' => count($webhooks), + 'total' => $includeTotal ? count($webhooks) : 0, ]), Response::MODEL_WEBHOOK_LIST); }); @@ -1530,9 +1531,10 @@ App::get('/v1/projects/:projectId/keys') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') - ->action(function (string $projectId, Response $response, Database $dbForPlatform) { + ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { $project = $dbForPlatform->getDocument('projects', $projectId); @@ -1547,7 +1549,7 @@ App::get('/v1/projects/:projectId/keys') $response->dynamic(new Document([ 'keys' => $keys, - 'total' => count($keys), + 'total' => $includeTotal ? count($keys) : 0, ]), Response::MODEL_KEY_LIST); }); @@ -1833,9 +1835,10 @@ App::get('/v1/projects/:projectId/platforms') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') - ->action(function (string $projectId, Response $response, Database $dbForPlatform) { + ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { $project = $dbForPlatform->getDocument('projects', $projectId); @@ -1850,7 +1853,7 @@ App::get('/v1/projects/:projectId/platforms') $response->dynamic(new Document([ 'platforms' => $platforms, - 'total' => count($platforms), + 'total' => $includeTotal ? count($platforms) : 0, ]), Response::MODEL_PLATFORM_LIST); }); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 8bc383cabd..59d63471d0 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -180,9 +180,10 @@ App::get('/v1/storage/buckets') )) ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -222,7 +223,7 @@ App::get('/v1/storage/buckets') $filterQueries = Query::groupByType($queries)['filters']; try { $buckets = $dbForProject->find('buckets', $queries); - $total = $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('buckets', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } catch (QueryException $e) { @@ -785,10 +786,11 @@ App::get('/v1/storage/buckets/:bucketId/files') ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('mode') - ->action(function (string $bucketId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { + ->action(function (string $bucketId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject, string $mode) { $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); @@ -846,10 +848,10 @@ App::get('/v1/storage/buckets/:bucketId/files') try { if ($fileSecurity && !$valid) { $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); - $total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0; } else { $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); + $total = $includeTotal ? Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)) : 0; } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 387fb7d48b..7e1443ba03 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -56,6 +56,7 @@ use Utopia\System\System; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; use Utopia\Validator\Text; +use Utopia\Validator\Boolean; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; @@ -172,9 +173,10 @@ App::get('/v1/teams') )) ->param('queries', [], new Teams(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -214,7 +216,7 @@ App::get('/v1/teams') $filterQueries = Query::groupByType($queries)['filters']; try { $results = $dbForProject->find('teams', $queries); - $total = $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } @@ -843,10 +845,11 @@ App::get('/v1/teams/:teamId/memberships') ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') - ->action(function (string $teamId, array $queries, string $search, Response $response, Document $project, Database $dbForProject) { + ->action(function (string $teamId, array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -898,11 +901,11 @@ App::get('/v1/teams/:teamId/memberships') collection: 'memberships', queries: $queries, ); - $total = $dbForProject->count( + $total = $includeTotal ? $dbForProject->count( collection: 'memberships', queries: $filterQueries, max: APP_LIMIT_COUNT - ); + ) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 1dfa5c2603..7f3966a0a0 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -646,9 +646,10 @@ App::get('/v1/users') )) ->param('queries', [], new Users(), '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(', ', Users::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -688,10 +689,10 @@ App::get('/v1/users') $users = []; $total = 0; - $dbForProject->skipFilters(function () use ($dbForProject, $queries, &$users, &$total) { + $dbForProject->skipFilters(function () use ($dbForProject, $queries, $includeTotal, &$users, &$total) { try { $users = $dbForProject->find('users', $queries); - $total = $dbForProject->count('users', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('users', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } catch (QueryException $e) { @@ -1030,9 +1031,10 @@ App::get('/v1/users/:userId/targets') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $userId, array $queries, Response $response, Database $dbForProject) { + ->action(function (string $userId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { $user = $dbForProject->getDocument('users', $userId); if ($user->isEmpty()) { @@ -1072,7 +1074,7 @@ App::get('/v1/users/:userId/targets') } try { $targets = $dbForProject->find('targets', $queries); - $total = $dbForProject->count('targets', $queries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('targets', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } @@ -1101,9 +1103,10 @@ App::get('/v1/users/identities') )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { + ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -1142,7 +1145,7 @@ App::get('/v1/users/identities') $filterQueries = Query::groupByType($queries)['filters']; try { $identities = $dbForProject->find('identities', $queries); - $total = $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 5bda9961f3..9e3bb64992 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -1458,11 +1458,12 @@ App::get('/v1/vcs/installations') )) ->param('queries', [], new Installations(), '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(', ', Installations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') ->inject('dbForPlatform') - ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForPlatform) { + ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Document $project, Database $dbForProject, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1503,7 +1504,7 @@ App::get('/v1/vcs/installations') $filterQueries = Query::groupByType($queries)['filters']; try { $results = $dbForPlatform->find('installations', $queries); - $total = $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } From 9f80952251f28f62a41009457bbea14632534171 Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 19 Oct 2025 16:15:13 +0300 Subject: [PATCH 05/20] linter --- app/controllers/api/teams.php | 2 +- .../Databases/Http/Databases/Collections/Documents/XList.php | 2 +- .../Modules/Databases/Http/Databases/Collections/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/XList.php | 2 +- .../Modules/Databases/Http/TablesDB/Tables/Rows/XList.php | 2 +- .../Platform/Modules/Databases/Http/TablesDB/Tables/XList.php | 2 +- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/XList.php | 2 +- .../Platform/Modules/Functions/Http/Functions/XList.php | 2 +- src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 7e1443ba03..75171c1fdc 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -55,8 +55,8 @@ use Utopia\Locale\Locale; use Utopia\System\System; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; use Utopia\Validator\URL; use Utopia\Validator\WhiteList; diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 719d6e6b7d..bb77e65a9e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -22,8 +22,8 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Action { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index 1751e0c1ef..53c53105b8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -19,8 +19,8 @@ use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Action { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 3e705dc954..54cbc25a48 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -18,8 +18,8 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Swoole\Response as SwooleResponse; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Action { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 21762883f7..beac29b2db 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -11,8 +11,8 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends DocumentXList { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index 52c2cc3170..98a8177223 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -11,8 +11,8 @@ use Appwrite\Utopia\Database\Validator\Queries\Tables; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends CollectionXList { diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php index 3ce4eba98b..32c6411803 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php @@ -10,8 +10,8 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Databases; use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Swoole\Response as SwooleResponse; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends DatabaseXList { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index acf171773b..7795fc129b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -19,8 +19,8 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Base { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php index d73a3dae97..3943a45c68 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -17,8 +17,8 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Base { diff --git a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php index 51a36ccb03..fc212c74b6 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php @@ -18,8 +18,8 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Action { diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php index 7f953cb70b..16730e4a8e 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php @@ -15,8 +15,8 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Action { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index cb82ad4cb9..8216188a9b 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -19,8 +19,8 @@ use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Base { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php index 31957a3094..405b0be68e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -17,8 +17,8 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Query\Cursor; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; -use Utopia\Validator\Text; use Utopia\Validator\Boolean; +use Utopia\Validator\Text; class XList extends Base { From 09075a05db5a8214b5cabfc8e6c86ee312c3a81c Mon Sep 17 00:00:00 2001 From: shimon Date: Sun, 19 Oct 2025 16:22:13 +0300 Subject: [PATCH 06/20] typo fix --- app/controllers/api/account.php | 2 +- app/controllers/api/messaging.php | 8 ++++---- app/controllers/api/migrations.php | 2 +- app/controllers/api/projects.php | 6 +++--- app/controllers/api/storage.php | 4 ++-- app/controllers/api/teams.php | 4 ++-- app/controllers/api/users.php | 6 +++--- app/controllers/api/vcs.php | 2 +- .../Http/Databases/Collections/Attributes/XList.php | 2 +- .../Http/Databases/Collections/Documents/XList.php | 2 +- .../Http/Databases/Collections/Indexes/XList.php | 2 +- .../Databases/Http/Databases/Collections/XList.php | 2 +- .../Platform/Modules/Databases/Http/Databases/XList.php | 2 +- .../Databases/Http/TablesDB/Tables/Columns/XList.php | 2 +- .../Databases/Http/TablesDB/Tables/Indexes/XList.php | 2 +- .../Modules/Databases/Http/TablesDB/Tables/Rows/XList.php | 2 +- .../Modules/Databases/Http/TablesDB/Tables/XList.php | 2 +- .../Platform/Modules/Databases/Http/TablesDB/XList.php | 2 +- .../Platform/Modules/Functions/Http/Deployments/XList.php | 2 +- .../Platform/Modules/Functions/Http/Executions/XList.php | 2 +- .../Platform/Modules/Functions/Http/Functions/XList.php | 2 +- .../Platform/Modules/Projects/Http/Projects/XList.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php | 2 +- .../Platform/Modules/Sites/Http/Deployments/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php | 2 +- src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php | 2 +- .../Modules/Tokens/Http/Tokens/Buckets/Files/XList.php | 2 +- 27 files changed, 36 insertions(+), 36 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 369df5c7b9..62beca5ce3 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -5304,7 +5304,7 @@ App::get('/v1/account/identities') contentType: ContentType::JSON )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('dbForProject') diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index bba2cb78e7..6f2ce1bbb4 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -985,7 +985,7 @@ App::get('/v1/messaging/providers') )) ->param('queries', [], new Providers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -2293,7 +2293,7 @@ App::get('/v1/messaging/topics') )) ->param('queries', [], new Topics(), '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(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -3513,7 +3513,7 @@ App::get('/v1/messaging/messages') )) ->param('queries', [], new Messages(), '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(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -3680,7 +3680,7 @@ App::get('/v1/messaging/messages/:messageId/targets') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $messageId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index f050ea2f15..2a605e95a9 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -460,7 +460,7 @@ App::get('/v1/migrations') )) ->param('queries', [], new Migrations(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Migrations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 1be73f598f..f335a70587 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1233,7 +1233,7 @@ App::get('/v1/projects/:projectId/webhooks') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { @@ -1531,7 +1531,7 @@ App::get('/v1/projects/:projectId/keys') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { @@ -1835,7 +1835,7 @@ App::get('/v1/projects/:projectId/platforms') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 59d63471d0..ecbd60128a 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -180,7 +180,7 @@ App::get('/v1/storage/buckets') )) ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -786,7 +786,7 @@ App::get('/v1/storage/buckets/:bucketId/files') ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('mode') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 75171c1fdc..b4c6f28a1b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -173,7 +173,7 @@ App::get('/v1/teams') )) ->param('queries', [], new Teams(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -845,7 +845,7 @@ App::get('/v1/teams/:teamId/memberships') ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 7f3966a0a0..72ba49d8d5 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -646,7 +646,7 @@ App::get('/v1/users') )) ->param('queries', [], new Users(), '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(', ', Users::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -1031,7 +1031,7 @@ App::get('/v1/users/:userId/targets') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $userId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { @@ -1103,7 +1103,7 @@ App::get('/v1/users/identities') )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 9e3bb64992..1cd0730aec 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -1458,7 +1458,7 @@ App::get('/v1/vcs/installations') )) ->param('queries', [], new Installations(), '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(', ', Installations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 1c340551d4..59953166e5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -61,7 +61,7 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->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) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index bb77e65a9e..2ecf7f293e 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -68,7 +68,7 @@ class XList extends Action ->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 ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 750d1e5bc4..cc7849d1c3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -63,7 +63,7 @@ class XList extends Action ->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) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index 53c53105b8..f45bc783f2 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -64,7 +64,7 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 54cbc25a48..c2c6e0b739 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -59,7 +59,7 @@ class XList extends Action ]) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 1476f73c4e..ced795093f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -49,7 +49,7 @@ class XList extends AttributesXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') ->param('queries', [], new Columns(), '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 columns: ' . implode(', ', Columns::ALLOWED_COLUMNS), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index a73e18b7b4..7adc983c88 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -51,7 +51,7 @@ class XList extends IndexXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->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 columns: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index beac29b2db..5729129095 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -53,7 +53,7 @@ class XList extends DocumentXList ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the TablesDB service [server integration](https://appwrite.io/docs/products/databases/tables#create-table).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index 98a8177223..0429a110e0 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -52,7 +52,7 @@ class XList extends CollectionXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Tables(), '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 columns: ' . implode(', ', Tables::ALLOWED_COLUMNS), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php index 32c6411803..d683e5839f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php @@ -45,7 +45,7 @@ class XList extends DatabaseXList )) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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 columns: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 7795fc129b..5032389a93 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index dac3697265..51105be494 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -57,7 +57,7 @@ class XList extends Base )) ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php index 3943a45c68..942e5581a4 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -55,7 +55,7 @@ class XList extends Base )) ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Functions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php index fc212c74b6..26bf6f0623 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php @@ -60,7 +60,7 @@ class XList extends Action )) ->param('queries', [], $this->getQueriesValidator(), '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(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php index 16730e4a8e..db42ce9ae5 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php @@ -52,7 +52,7 @@ class XList extends Action )) ->param('queries', [], new Rules(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Rules::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForPlatform') diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index 8216188a9b..6bfed20dde 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index 05d03af0ff..29eb06a171 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -56,7 +56,7 @@ class XList extends Base )) ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Logs(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php index 405b0be68e..bf5faaf0d6 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -55,7 +55,7 @@ class XList extends Base )) ->param('queries', [], new Sites(), '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(', ', Sites::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 68e03160bb..3170aa007b 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -54,7 +54,7 @@ class XList extends Action ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') ->param('queries', [], new FileTokens(), '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(', ', FileTokens::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total countreturend will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); From fb4e3e1b9db5a229e980a66a5b13babb8868ddcc Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 20 Oct 2025 18:18:17 +0300 Subject: [PATCH 07/20] Implement 'includeTotal' parameter across multiple API endpoints to control total count in responses, ensuring consistent behavior in session, log, and membership retrievals. --- app/controllers/api/account.php | 10 ++-- app/controllers/api/messaging.php | 20 +++++--- app/controllers/api/teams.php | 5 +- app/controllers/api/users.php | 15 +++--- .../Functions/Http/Templates/XList.php | 6 ++- .../Account/AccountCustomClientTest.php | 19 +++++++ .../Databases/Legacy/DatabasesBase.php | 18 +++++++ .../Legacy/DatabasesCustomServerTest.php | 51 +++++++++++++++++++ .../TablesDB/DatabasesCustomServerTest.php | 17 +++++++ .../Functions/FunctionsCustomClientTest.php | 17 +++++++ .../Functions/FunctionsCustomServerTest.php | 24 +++++++++ .../e2e/Services/Messaging/MessagingBase.php | 18 +++++++ tests/e2e/Services/Storage/StorageBase.php | 17 +++++++ tests/e2e/Services/Teams/TeamsBase.php | 17 +++++++ tests/e2e/Services/Users/UsersBase.php | 17 +++++++ 15 files changed, 249 insertions(+), 22 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 62beca5ce3..a17c1bf468 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -553,12 +553,13 @@ App::get('/v1/account/sessions') ], contentType: ContentType::JSON, )) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') ->inject('store') ->inject('proofForToken') - ->action(function (Response $response, Document $user, Locale $locale, Store $store, ProofsToken $proofForToken) { + ->action(function (bool $includeTotal, Response $response, Document $user, Locale $locale, Store $store, ProofsToken $proofForToken) { $sessions = $user->getAttribute('sessions', []); @@ -576,7 +577,7 @@ App::get('/v1/account/sessions') $response->dynamic(new Document([ 'sessions' => $sessions, - 'total' => count($sessions), + 'total' => $includeTotal ? count($sessions) : 0, ]), Response::MODEL_SESSION_LIST); }); @@ -2879,12 +2880,13 @@ App::get('/v1/account/logs') contentType: ContentType::JSON, )) ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') ->inject('geodb') ->inject('dbForProject') - ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { + ->action(function (array $queries, bool $includeTotal, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -2929,7 +2931,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getSequence(), $queries), + 'total' => $includeTotal ? $audit->countLogsByUser($user->getSequence(), $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 6f2ce1bbb4..0ad0f5ea1b 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1054,11 +1054,12 @@ App::get('/v1/messaging/providers/:providerId/logs') )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $providerId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $providerId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $provider = $dbForProject->getDocument('providers', $providerId); if ($provider->isEmpty()) { @@ -1126,7 +1127,7 @@ App::get('/v1/messaging/providers/:providerId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), + 'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2362,11 +2363,12 @@ App::get('/v1/messaging/topics/:topicId/logs') )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $topicId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $topicId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $topic = $dbForProject->getDocument('topics', $topicId); if ($topic->isEmpty()) { @@ -2435,7 +2437,7 @@ App::get('/v1/messaging/topics/:topicId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), + 'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2783,11 +2785,12 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') )) ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $subscriberId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $subscriberId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $subscriber = $dbForProject->getDocument('subscribers', $subscriberId); if ($subscriber->isEmpty()) { @@ -2856,7 +2859,7 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), + 'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -3582,11 +3585,12 @@ App::get('/v1/messaging/messages/:messageId/logs') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $messageId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3655,7 +3659,7 @@ App::get('/v1/messaging/messages/:messageId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), + 'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index b4c6f28a1b..bed07235e8 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1445,11 +1445,12 @@ App::get('/v1/teams/:teamId/logs') )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $teamId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $team = $dbForProject->getDocument('teams', $teamId); @@ -1518,7 +1519,7 @@ App::get('/v1/teams/:teamId/logs') } } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource, $queries), + 'total' => $includeTotal ? $audit->countLogsByResource($resource, $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 72ba49d8d5..64ce5c0970 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -826,10 +826,11 @@ App::get('/v1/users/:userId/sessions') ] )) ->param('userId', '', new UID(), 'User ID.') + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') - ->action(function (string $userId, Response $response, Database $dbForProject, Locale $locale) { + ->action(function (string $userId, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale) { $user = $dbForProject->getDocument('users', $userId); @@ -851,7 +852,7 @@ App::get('/v1/users/:userId/sessions') $response->dynamic(new Document([ 'sessions' => $sessions, - 'total' => count($sessions), + 'total' => $includeTotal ? count($sessions) : 0, ]), Response::MODEL_SESSION_LIST); }); @@ -875,9 +876,10 @@ App::get('/v1/users/:userId/memberships') ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $userId, array $queries, string $search, Response $response, Database $dbForProject) { + ->action(function (string $userId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { $user = $dbForProject->getDocument('users', $userId); @@ -911,7 +913,7 @@ App::get('/v1/users/:userId/memberships') $response->dynamic(new Document([ 'memberships' => $memberships, - 'total' => count($memberships), + 'total' => $includeTotal ? count($memberships) : 0, ]), Response::MODEL_MEMBERSHIP_LIST); }); @@ -934,11 +936,12 @@ App::get('/v1/users/:userId/logs') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') ->inject('geodb') - ->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $userId, array $queries, bool $includeTotal, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { $user = $dbForProject->getDocument('users', $userId); @@ -1007,7 +1010,7 @@ App::get('/v1/users/:userId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getSequence(), $queries), + 'total' => $includeTotal ? $audit->countLogsByUser($user->getSequence(), $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php index 86e7f21362..c9c4dbc500 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php @@ -12,6 +12,7 @@ use Utopia\Database\Document; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\ArrayList; +use Utopia\Validator\Boolean; use Utopia\Validator\Range; use Utopia\Validator\WhiteList; @@ -52,11 +53,12 @@ class XList extends Base ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->callback($this->action(...)); } - public function action(array $runtimes, array $usecases, int $limit, int $offset, Response $response) + public function action(array $runtimes, array $usecases, int $limit, int $offset, bool $includeTotal, Response $response) { $templates = Config::getParam('templates-function', []); @@ -76,7 +78,7 @@ class XList extends Base return $b['score'] <=> $a['score']; }); - $total = \count($templates); + $total = $includeTotal ? \count($templates) : 0; $templates = \array_slice($templates, $offset, $limit); $response->dynamic(new Document([ 'templates' => $templates, diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 0993f68a58..b4e9c218ed 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -236,6 +236,25 @@ class AccountCustomClientTest extends Scope $this->assertEquals($sessionId, $response['body']['sessions'][0]['$id']); $this->assertEmpty($response['body']['sessions'][0]['secret']); + /** + * Test for SUCCESS with includeTotal=false + */ + $sessionsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/account/sessions', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]), [ + 'includeTotal' => false + ]); + + $this->assertEquals($sessionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($sessionsWithIncludeTotalFalse['body']); + $this->assertIsArray($sessionsWithIncludeTotalFalse['body']['sessions']); + $this->assertIsInt($sessionsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $sessionsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($sessionsWithIncludeTotalFalse['body']['sessions'])); + $this->assertEquals('Windows', $response['body']['sessions'][0]['osName']); $this->assertEquals('WIN', $response['body']['sessions'][0]['osCode']); $this->assertEquals('10', $response['body']['sessions'][0]['osVersion']); diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php index bfc56567ef..6a2f3e617e 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php @@ -961,6 +961,24 @@ trait DatabasesBase $this->assertEquals(200, $attributes['headers']['status-code']); $this->assertEquals(12, $attributes['body']['total']); + /** + * Test for SUCCESS with includeTotal=false + */ + $attributesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'includeTotal' => false + ]); + + $this->assertEquals($attributesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($attributesWithIncludeTotalFalse['body']); + $this->assertIsArray($attributesWithIncludeTotalFalse['body']['attributes']); + $this->assertIsInt($attributesWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $attributesWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($attributesWithIncludeTotalFalse['body']['attributes'])); + $attributes = $attributes['body']['attributes']; $this->assertIsArray($attributes); $this->assertCount(12, $attributes); diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php index c1ce75c38d..04faea28a9 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php @@ -55,6 +55,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test1['body']['$id'], $databases['body']['databases'][0]['$id']); $this->assertEquals($test2['body']['$id'], $databases['body']['databases'][1]['$id']); + /** + * Test for SUCCESS with includeTotal=false + */ + $databasesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($databasesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($databasesWithIncludeTotalFalse['body']); + $this->assertIsArray($databasesWithIncludeTotalFalse['body']['databases']); + $this->assertIsInt($databasesWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $databasesWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($databasesWithIncludeTotalFalse['body']['databases'])); + $base = array_reverse($databases['body']['databases']); $databases = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ @@ -395,6 +412,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test2['body']['$id'], $collections['body']['collections'][1]['$id']); $this->assertEquals($test1['body']['enabled'], $collections['body']['collections'][0]['enabled']); + /** + * Test for SUCCESS with includeTotal=false + */ + $collectionsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($collectionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($collectionsWithIncludeTotalFalse['body']); + $this->assertIsArray($collectionsWithIncludeTotalFalse['body']['collections']); + $this->assertIsInt($collectionsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $collectionsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($collectionsWithIncludeTotalFalse['body']['collections'])); + $base = array_reverse($collections['body']['collections']); $collections = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ @@ -4548,6 +4582,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $documents['headers']['status-code']); $this->assertEquals(10, $documents['body']['total']); + /** + * Test for SUCCESS with includeTotal=false + */ + $documentsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($documentsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($documentsWithIncludeTotalFalse['body']); + $this->assertIsArray($documentsWithIncludeTotalFalse['body']['documents']); + $this->assertIsInt($documentsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $documentsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($documentsWithIncludeTotalFalse['body']['documents'])); + $returnedDocuments = $response['body']['documents']; $refetchedDocuments = $documents['body']['documents']; diff --git a/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php index 5e35fa065d..68e6cad286 100644 --- a/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php @@ -55,6 +55,23 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test1['body']['$id'], $databases['body']['databases'][0]['$id']); $this->assertEquals($test2['body']['$id'], $databases['body']['databases'][1]['$id']); + /** + * Test for SUCCESS with includeTotal=false + */ + $databasesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/tablesdb', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($databasesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($databasesWithIncludeTotalFalse['body']); + $this->assertIsArray($databasesWithIncludeTotalFalse['body']['databases']); + $this->assertIsInt($databasesWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $databasesWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($databasesWithIncludeTotalFalse['body']['databases'])); + $base = array_reverse($databases['body']['databases']); $databases = $this->client->call(Client::METHOD_GET, '/tablesdb', array_merge([ diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index c3c9fbfbab..21e0d38205 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -376,6 +376,23 @@ class FunctionsCustomClientTest extends Scope $this->assertGreaterThan(0, $templates['body']['total']); $this->assertIsArray($templates['body']['templates']); + /** + * Test for SUCCESS with includeTotal=false + */ + $templatesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($templatesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($templatesWithIncludeTotalFalse['body']); + $this->assertIsArray($templatesWithIncludeTotalFalse['body']['templates']); + $this->assertIsInt($templatesWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $templatesWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($templatesWithIncludeTotalFalse['body']['templates'])); + foreach ($templates['body']['templates'] as $template) { $this->assertArrayHasKey('name', $template); $this->assertArrayHasKey('id', $template); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 0d63791151..53cff987d3 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -418,6 +418,18 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployments['headers']['status-code']); $this->assertEquals(1, $deployments['body']['total']); + /** + * Test for SUCCESS with includeTotal=false + */ + $deploymentsWithIncludeTotalFalse = $this->listDeployments($functionId, ['includeTotal' => false]); + + $this->assertEquals($deploymentsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($deploymentsWithIncludeTotalFalse['body']); + $this->assertIsArray($deploymentsWithIncludeTotalFalse['body']['deployments']); + $this->assertIsInt($deploymentsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $deploymentsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($deploymentsWithIncludeTotalFalse['body']['deployments'])); + $lastDeployment = $deployments['body']['deployments'][0]; $this->assertNotEmpty($lastDeployment['$id']); @@ -1004,6 +1016,18 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $executions['body']['executions']); $this->assertEquals($data['deploymentId'], $executions['body']['executions'][0]['deploymentId']); + /** + * Test for SUCCESS with includeTotal=false + */ + $executionsWithIncludeTotalFalse = $this->listExecutions($data['functionId'], ['includeTotal' => false]); + + $this->assertEquals($executionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($executionsWithIncludeTotalFalse['body']); + $this->assertIsArray($executionsWithIncludeTotalFalse['body']['executions']); + $this->assertIsInt($executionsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $executionsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($executionsWithIncludeTotalFalse['body']['executions'])); + $executions = $this->listExecutions($data['functionId'], [ 'queries' => [ Query::equal('deploymentId', [$data['deploymentId']])->toString(), diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index dc5ddb9d70..456d458414 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -633,6 +633,24 @@ trait MessagingBase $this->assertEquals(1, $response['body']['total']); } + /** + * Test for SUCCESS with includeTotal=false + */ + $subscribersWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/messaging/topics/' . $data['topicId'] . '/subscribers', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'includeTotal' => false + ]); + + $this->assertEquals($subscribersWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($subscribersWithIncludeTotalFalse['body']); + $this->assertIsArray($subscribersWithIncludeTotalFalse['body']['subscribers']); + $this->assertIsInt($subscribersWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $subscribersWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($subscribersWithIncludeTotalFalse['body']['subscribers'])); + return $data; } diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 2b2c884283..943283d185 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -379,6 +379,23 @@ trait StorageBase $this->assertGreaterThan(0, $files['body']['total']); $this->assertGreaterThan(0, count($files['body']['files'])); + /** + * Test for SUCCESS with includeTotal=false + */ + $filesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($filesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($filesWithIncludeTotalFalse['body']); + $this->assertIsArray($filesWithIncludeTotalFalse['body']['files']); + $this->assertIsInt($filesWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $filesWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($filesWithIncludeTotalFalse['body']['files'])); + $files = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index fccfded1e1..4320ef8c6b 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -322,6 +322,23 @@ trait TeamsBase $this->assertEquals(400, $response['headers']['status-code']); + /** + * Test for SUCCESS with includeTotal=false + */ + $teamsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($teamsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($teamsWithIncludeTotalFalse['body']); + $this->assertIsArray($teamsWithIncludeTotalFalse['body']['teams']); + $this->assertIsInt($teamsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $teamsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($teamsWithIncludeTotalFalse['body']['teams'])); + return []; } diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 2cf1e4c65d..bce411906d 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -798,6 +798,23 @@ trait UsersBase $this->assertIsInt($users['body']['total']); $this->assertGreaterThan(0, $users['body']['total']); + /** + * Test for SUCCESS with includeTotal=false + */ + $usersWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'includeTotal' => false + ]); + + $this->assertEquals($usersWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertIsArray($usersWithIncludeTotalFalse['body']); + $this->assertIsArray($usersWithIncludeTotalFalse['body']['users']); + $this->assertIsInt($usersWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $usersWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($usersWithIncludeTotalFalse['body']['users'])); + /** * Test for FAILURE */ From 5f3316ff189addd1fb2b283e4e266696db9c7377 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 20 Oct 2025 18:38:14 +0300 Subject: [PATCH 08/20] fix assertion order --- tests/e2e/Services/Account/AccountCustomClientTest.php | 2 +- tests/e2e/Services/Databases/Legacy/DatabasesBase.php | 2 +- .../Services/Databases/Legacy/DatabasesCustomServerTest.php | 6 +++--- .../Databases/TablesDB/DatabasesCustomServerTest.php | 2 +- tests/e2e/Services/Functions/FunctionsCustomClientTest.php | 2 +- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 4 ++-- tests/e2e/Services/Messaging/MessagingBase.php | 2 +- tests/e2e/Services/Storage/StorageBase.php | 2 +- tests/e2e/Services/Teams/TeamsBase.php | 2 +- tests/e2e/Services/Users/UsersBase.php | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index b4e9c218ed..ae21ae75a8 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -248,7 +248,7 @@ class AccountCustomClientTest extends Scope 'includeTotal' => false ]); - $this->assertEquals($sessionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $sessionsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($sessionsWithIncludeTotalFalse['body']); $this->assertIsArray($sessionsWithIncludeTotalFalse['body']['sessions']); $this->assertIsInt($sessionsWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php index 84b00bc8e2..ec1c7632ed 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php @@ -972,7 +972,7 @@ trait DatabasesBase 'includeTotal' => false ]); - $this->assertEquals($attributesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $attributesWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($attributesWithIncludeTotalFalse['body']); $this->assertIsArray($attributesWithIncludeTotalFalse['body']['attributes']); $this->assertIsInt($attributesWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php index 04faea28a9..f9fcf24c18 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php @@ -65,7 +65,7 @@ class DatabasesCustomServerTest extends Scope 'includeTotal' => false ]); - $this->assertEquals($databasesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $databasesWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($databasesWithIncludeTotalFalse['body']); $this->assertIsArray($databasesWithIncludeTotalFalse['body']['databases']); $this->assertIsInt($databasesWithIncludeTotalFalse['body']['total']); @@ -422,7 +422,7 @@ class DatabasesCustomServerTest extends Scope 'includeTotal' => false ]); - $this->assertEquals($collectionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $collectionsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($collectionsWithIncludeTotalFalse['body']); $this->assertIsArray($collectionsWithIncludeTotalFalse['body']['collections']); $this->assertIsInt($collectionsWithIncludeTotalFalse['body']['total']); @@ -4592,7 +4592,7 @@ class DatabasesCustomServerTest extends Scope 'includeTotal' => false ]); - $this->assertEquals($documentsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $documentsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($documentsWithIncludeTotalFalse['body']); $this->assertIsArray($documentsWithIncludeTotalFalse['body']['documents']); $this->assertIsInt($documentsWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php index 68e6cad286..5db78ed9a1 100644 --- a/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php @@ -65,7 +65,7 @@ class DatabasesCustomServerTest extends Scope 'includeTotal' => false ]); - $this->assertEquals($databasesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $databasesWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($databasesWithIncludeTotalFalse['body']); $this->assertIsArray($databasesWithIncludeTotalFalse['body']['databases']); $this->assertIsInt($databasesWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 21e0d38205..5e1fd8881e 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -386,7 +386,7 @@ class FunctionsCustomClientTest extends Scope 'includeTotal' => false ]); - $this->assertEquals($templatesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $templatesWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($templatesWithIncludeTotalFalse['body']); $this->assertIsArray($templatesWithIncludeTotalFalse['body']['templates']); $this->assertIsInt($templatesWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 53cff987d3..b0a05bf591 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -423,7 +423,7 @@ class FunctionsCustomServerTest extends Scope */ $deploymentsWithIncludeTotalFalse = $this->listDeployments($functionId, ['includeTotal' => false]); - $this->assertEquals($deploymentsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $deploymentsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($deploymentsWithIncludeTotalFalse['body']); $this->assertIsArray($deploymentsWithIncludeTotalFalse['body']['deployments']); $this->assertIsInt($deploymentsWithIncludeTotalFalse['body']['total']); @@ -1021,7 +1021,7 @@ class FunctionsCustomServerTest extends Scope */ $executionsWithIncludeTotalFalse = $this->listExecutions($data['functionId'], ['includeTotal' => false]); - $this->assertEquals($executionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $executionsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($executionsWithIncludeTotalFalse['body']); $this->assertIsArray($executionsWithIncludeTotalFalse['body']['executions']); $this->assertIsInt($executionsWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 456d458414..e4d40aaf68 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -644,7 +644,7 @@ trait MessagingBase 'includeTotal' => false ]); - $this->assertEquals($subscribersWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $subscribersWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($subscribersWithIncludeTotalFalse['body']); $this->assertIsArray($subscribersWithIncludeTotalFalse['body']['subscribers']); $this->assertIsInt($subscribersWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 943283d185..361e561283 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -389,7 +389,7 @@ trait StorageBase 'includeTotal' => false ]); - $this->assertEquals($filesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $filesWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($filesWithIncludeTotalFalse['body']); $this->assertIsArray($filesWithIncludeTotalFalse['body']['files']); $this->assertIsInt($filesWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 4320ef8c6b..ae85e80b91 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -332,7 +332,7 @@ trait TeamsBase 'includeTotal' => false ]); - $this->assertEquals($teamsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $teamsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($teamsWithIncludeTotalFalse['body']); $this->assertIsArray($teamsWithIncludeTotalFalse['body']['teams']); $this->assertIsInt($teamsWithIncludeTotalFalse['body']['total']); diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index bce411906d..aaa00c98ff 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -808,7 +808,7 @@ trait UsersBase 'includeTotal' => false ]); - $this->assertEquals($usersWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $usersWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($usersWithIncludeTotalFalse['body']); $this->assertIsArray($usersWithIncludeTotalFalse['body']['users']); $this->assertIsInt($usersWithIncludeTotalFalse['body']['total']); From a643cde26d6752d548ed4a4b378b195ac9e6ced6 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 20 Oct 2025 22:00:57 +0300 Subject: [PATCH 09/20] Update 'includeTotal' parameter to use Boolean(true) for consistent behavior across API endpoints, enhancing response handling for sessions, logs, memberships, and more. --- app/controllers/api/account.php | 6 +++--- app/controllers/api/messaging.php | 16 ++++++++-------- app/controllers/api/migrations.php | 2 +- app/controllers/api/projects.php | 6 +++--- app/controllers/api/storage.php | 4 ++-- app/controllers/api/teams.php | 6 +++--- app/controllers/api/users.php | 12 ++++++------ app/controllers/api/vcs.php | 2 +- composer.lock | 8 ++++---- .../Databases/Collections/Attributes/XList.php | 2 +- .../Databases/Collections/Documents/XList.php | 2 +- .../Http/Databases/Collections/Indexes/XList.php | 2 +- .../Http/Databases/Collections/XList.php | 2 +- .../Modules/Databases/Http/Databases/XList.php | 2 +- .../Http/TablesDB/Tables/Columns/XList.php | 2 +- .../Http/TablesDB/Tables/Indexes/XList.php | 2 +- .../Http/TablesDB/Tables/Rows/XList.php | 2 +- .../Databases/Http/TablesDB/Tables/XList.php | 2 +- .../Modules/Databases/Http/TablesDB/XList.php | 2 +- .../Modules/Functions/Http/Deployments/XList.php | 2 +- .../Modules/Functions/Http/Executions/XList.php | 2 +- .../Modules/Functions/Http/Functions/XList.php | 2 +- .../Modules/Functions/Http/Templates/XList.php | 2 +- .../Modules/Projects/Http/Projects/XList.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/XList.php | 2 +- .../Modules/Sites/Http/Deployments/XList.php | 2 +- .../Platform/Modules/Sites/Http/Logs/XList.php | 2 +- .../Platform/Modules/Sites/Http/Sites/XList.php | 2 +- .../Tokens/Http/Tokens/Buckets/Files/XList.php | 2 +- 29 files changed, 51 insertions(+), 51 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index a17c1bf468..85884789ee 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -553,7 +553,7 @@ App::get('/v1/account/sessions') ], contentType: ContentType::JSON, )) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') @@ -2880,7 +2880,7 @@ App::get('/v1/account/logs') contentType: ContentType::JSON, )) ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') @@ -5306,7 +5306,7 @@ App::get('/v1/account/identities') contentType: ContentType::JSON )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('dbForProject') diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 0ad0f5ea1b..81d83195e9 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -985,7 +985,7 @@ App::get('/v1/messaging/providers') )) ->param('queries', [], new Providers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -1054,7 +1054,7 @@ App::get('/v1/messaging/providers/:providerId/logs') )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -2294,7 +2294,7 @@ App::get('/v1/messaging/topics') )) ->param('queries', [], new Topics(), '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(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -2363,7 +2363,7 @@ App::get('/v1/messaging/topics/:topicId/logs') )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -2785,7 +2785,7 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') )) ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -3516,7 +3516,7 @@ App::get('/v1/messaging/messages') )) ->param('queries', [], new Messages(), '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(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -3585,7 +3585,7 @@ App::get('/v1/messaging/messages/:messageId/logs') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -3684,7 +3684,7 @@ App::get('/v1/messaging/messages/:messageId/targets') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $messageId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 2a605e95a9..1efa11f222 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -460,7 +460,7 @@ App::get('/v1/migrations') )) ->param('queries', [], new Migrations(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Migrations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index f335a70587..65fe278834 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1233,7 +1233,7 @@ App::get('/v1/projects/:projectId/webhooks') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { @@ -1531,7 +1531,7 @@ App::get('/v1/projects/:projectId/keys') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { @@ -1835,7 +1835,7 @@ App::get('/v1/projects/:projectId/platforms') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index ecbd60128a..70adbfa717 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -180,7 +180,7 @@ App::get('/v1/storage/buckets') )) ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -786,7 +786,7 @@ App::get('/v1/storage/buckets/:bucketId/files') ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('mode') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index bed07235e8..a7829d7adc 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -173,7 +173,7 @@ App::get('/v1/teams') )) ->param('queries', [], new Teams(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -845,7 +845,7 @@ App::get('/v1/teams/:teamId/memberships') ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') @@ -1445,7 +1445,7 @@ App::get('/v1/teams/:teamId/logs') )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 64ce5c0970..da24d1174d 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -646,7 +646,7 @@ App::get('/v1/users') )) ->param('queries', [], new Users(), '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(', ', Users::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -826,7 +826,7 @@ App::get('/v1/users/:userId/sessions') ] )) ->param('userId', '', new UID(), 'User ID.') - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -876,7 +876,7 @@ App::get('/v1/users/:userId/memberships') ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $userId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -936,7 +936,7 @@ App::get('/v1/users/:userId/logs') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -1034,7 +1034,7 @@ App::get('/v1/users/:userId/targets') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $userId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { @@ -1106,7 +1106,7 @@ App::get('/v1/users/identities') )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 1cd0730aec..a854626629 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -1458,7 +1458,7 @@ App::get('/v1/vcs/installations') )) ->param('queries', [], new Installations(), '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(', ', Installations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') diff --git a/composer.lock b/composer.lock index f65e715647..66b9c9f48c 100644 --- a/composer.lock +++ b/composer.lock @@ -3899,9 +3899,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.0.0" + "source": "https://github.com/utopia-php/database/tree/3.0.1" }, - "time": "2025-10-20T05:51:31+00:00" + "time": "2025-10-20T13:21:17+00:00" }, { "name": "utopia-php/detector", @@ -8793,7 +8793,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8817,5 +8817,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index 59953166e5..a611e04de9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -61,7 +61,7 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->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) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 2ecf7f293e..04d0f85fb6 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -68,7 +68,7 @@ class XList extends Action ->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 ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index cc7849d1c3..223fa7dd87 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -63,7 +63,7 @@ class XList extends Action ->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) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index f45bc783f2..2ce88c3b25 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -64,7 +64,7 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index c2c6e0b739..5a792093e8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -59,7 +59,7 @@ class XList extends Action ]) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index ced795093f..8eebf0260f 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -49,7 +49,7 @@ class XList extends AttributesXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') ->param('queries', [], new Columns(), '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 columns: ' . implode(', ', Columns::ALLOWED_COLUMNS), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index 7adc983c88..1bac24a1dd 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -51,7 +51,7 @@ class XList extends IndexXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->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 columns: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 5729129095..9ce815d2ab 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -53,7 +53,7 @@ class XList extends DocumentXList ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the TablesDB service [server integration](https://appwrite.io/docs/products/databases/tables#create-table).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index 0429a110e0..efe066773b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -52,7 +52,7 @@ class XList extends CollectionXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Tables(), '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 columns: ' . implode(', ', Tables::ALLOWED_COLUMNS), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php index d683e5839f..1653f1ca50 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php @@ -45,7 +45,7 @@ class XList extends DatabaseXList )) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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 columns: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 5032389a93..243c2ee5f3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 51105be494..3442280a0c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -57,7 +57,7 @@ class XList extends Base )) ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php index 942e5581a4..a5af6fb89c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -55,7 +55,7 @@ class XList extends Base )) ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Functions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php index c9c4dbc500..b29f42a7bc 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php @@ -53,7 +53,7 @@ class XList extends Base ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php index 26bf6f0623..ddd38a3851 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php @@ -60,7 +60,7 @@ class XList extends Action )) ->param('queries', [], $this->getQueriesValidator(), '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(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php index db42ce9ae5..bba279fea1 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php @@ -52,7 +52,7 @@ class XList extends Action )) ->param('queries', [], new Rules(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Rules::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForPlatform') diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index 6bfed20dde..729bb2798b 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index 29eb06a171..0de403a03f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -56,7 +56,7 @@ class XList extends Base )) ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Logs(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php index bf5faaf0d6..be3f1cc60a 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -55,7 +55,7 @@ class XList extends Base )) ->param('queries', [], new Sites(), '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(', ', Sites::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 3170aa007b..ac78b482ec 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -54,7 +54,7 @@ class XList extends Action ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') ->param('queries', [], new FileTokens(), '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(', ', FileTokens::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); From bb0889fdba0de26975f6c8d90412c955372d99ab Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 21 Oct 2025 10:35:01 +0300 Subject: [PATCH 10/20] test fix --- app/controllers/api/messaging.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 81d83195e9..2586df48be 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2697,9 +2697,10 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('queries', [], new Subscribers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') - ->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -2761,7 +2762,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') $response ->dynamic(new Document([ 'subscribers' => $subscribers, - 'total' => $dbForProject->count('subscribers', $queries, APP_LIMIT_COUNT), + 'total' => $includeTotal ? $dbForProject->count('subscribers', $queries, APP_LIMIT_COUNT) : 0, ]), Response::MODEL_SUBSCRIBER_LIST); }); From 095ee8511b26095f2af1c5cd95a5204626e2ab19 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 21 Oct 2025 10:44:17 +0300 Subject: [PATCH 11/20] composer --- composer.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/composer.lock b/composer.lock index 66b9c9f48c..b426c5ddcd 100644 --- a/composer.lock +++ b/composer.lock @@ -3847,16 +3847,16 @@ }, { "name": "utopia-php/database", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "da0d583e1590e37515edfa338d8684c01833455f" + "reference": "b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/da0d583e1590e37515edfa338d8684c01833455f", - "reference": "da0d583e1590e37515edfa338d8684c01833455f", + "url": "https://api.github.com/repos/utopia-php/database/zipball/b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e", + "reference": "b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e", "shasum": "" }, "require": { @@ -3866,7 +3866,7 @@ "php": ">=8.1", "utopia-php/cache": "0.13.*", "utopia-php/framework": "0.33.*", - "utopia-php/mongo": "0.10.*", + "utopia-php/mongo": "0.11.*", "utopia-php/pools": "0.8.*" }, "require-dev": { @@ -3899,9 +3899,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.0.1" + "source": "https://github.com/utopia-php/database/tree/3.0.2" }, - "time": "2025-10-20T13:21:17+00:00" + "time": "2025-10-20T23:58:56+00:00" }, { "name": "utopia-php/detector", @@ -4457,16 +4457,16 @@ }, { "name": "utopia-php/mongo", - "version": "0.10.0", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/utopia-php/mongo.git", - "reference": "ecfad6aad2e2e3fe5899ac2ebf1009a21b4d6b18" + "reference": "34bc0cda8ea368cde68702a6fffe2c3ac625398e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/mongo/zipball/ecfad6aad2e2e3fe5899ac2ebf1009a21b4d6b18", - "reference": "ecfad6aad2e2e3fe5899ac2ebf1009a21b4d6b18", + "url": "https://api.github.com/repos/utopia-php/mongo/zipball/34bc0cda8ea368cde68702a6fffe2c3ac625398e", + "reference": "34bc0cda8ea368cde68702a6fffe2c3ac625398e", "shasum": "" }, "require": { @@ -4512,9 +4512,9 @@ ], "support": { "issues": "https://github.com/utopia-php/mongo/issues", - "source": "https://github.com/utopia-php/mongo/tree/0.10.0" + "source": "https://github.com/utopia-php/mongo/tree/0.11.0" }, - "time": "2025-10-02T04:50:07+00:00" + "time": "2025-10-20T11:11:23+00:00" }, { "name": "utopia-php/orchestration", @@ -5279,16 +5279,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.4", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49" + "reference": "0c4f514bf861f42555dae781f394fefeb27ff521" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49", - "reference": "a20b20cfd70a1879f0d0fb2b4f669aa5ed836c49", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0c4f514bf861f42555dae781f394fefeb27ff521", + "reference": "0c4f514bf861f42555dae781f394fefeb27ff521", "shasum": "" }, "require": { @@ -5324,9 +5324,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.4" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.5" }, - "time": "2025-10-13T09:20:49+00:00" + "time": "2025-10-21T04:59:59+00:00" }, { "name": "doctrine/annotations", From c8f8b6ff0ca935f56af8bab1a9af9cfae537259d Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 21 Oct 2025 10:54:03 +0300 Subject: [PATCH 12/20] account sync --- app/controllers/api/account.php | 1190 ++++++++++--------------------- 1 file changed, 362 insertions(+), 828 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 85884789ee..66327e2f3d 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -25,7 +25,6 @@ use Appwrite\Network\Validator\Redirect; use Appwrite\OpenSSL\OpenSSL; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; -use Appwrite\SDK\Deprecated; use Appwrite\SDK\Method; use Appwrite\SDK\MethodType; use Appwrite\SDK\Response as SDKResponse; @@ -40,11 +39,6 @@ use MaxMind\Db\Reader; use Utopia\Abuse\Abuse; use Utopia\App; use Utopia\Audit\Audit as EventAudit; -use Utopia\Auth\Hashes\Sha; -use Utopia\Auth\Proofs\Code as ProofsCode; -use Utopia\Auth\Proofs\Password as ProofsPassword; -use Utopia\Auth\Proofs\Token as ProofsToken; -use Utopia\Auth\Store; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -63,7 +57,6 @@ use Utopia\Database\Validator\Query\Limit; use Utopia\Database\Validator\Query\Offset; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; -use Utopia\Storage\Validator\FileName; use Utopia\System\System; use Utopia\Validator\ArrayList; use Utopia\Validator\Assoc; @@ -78,7 +71,6 @@ $oauthDefaultFailure = '/console/auth/oauth2/failure'; function sendSessionAlert(Locale $locale, Document $user, Document $project, Document $session, Mail $queueForMails) { $subject = $locale->getText("emails.sessionAlert.subject"); - $preview = $locale->getText("emails.sessionAlert.preview"); $customTemplate = $project->getAttribute('templates', [])['email.sessionAlert-' . $locale->default] ?? []; $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-session-alert.tpl'); @@ -140,16 +132,6 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc ->setSmtpSenderName($senderName); } - // session alerts should always have a client name! - $clientName = $session->getAttribute('clientName'); - if (empty($clientName)) { - // fallback to the user agent and then unknown! - $userAgent = $session->getAttribute('userAgent'); - $clientName = !empty($userAgent) ? $userAgent : 'UNKNOWN'; - - $session->setAttribute('clientName', $clientName); - } - $emailVariables = [ 'direction' => $locale->getText('settings.direction'), 'date' => (new \DateTime())->format('F j'), @@ -166,15 +148,14 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc $queueForMails ->setSubject($subject) - ->setPreview($preview) ->setBody($body) ->setVariables($emailVariables) ->setRecipient($email) ->trigger(); -} -; +}; -$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Store $store, ProofsToken $proofForToken, ProofsCode $proofForCode) { + +$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails) { /** @var Utopia\Database\Document $user */ $userFromRequest = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); @@ -183,8 +164,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res throw new Exception(Exception::USER_INVALID_TOKEN); } - $verifiedToken = Auth::tokenVerify($userFromRequest->getAttribute('tokens', []), null, $secret, $proofForToken) - ?: Auth::tokenVerify($userFromRequest->getAttribute('tokens', []), null, $secret, $proofForCode); + $verifiedToken = Auth::tokenVerify($userFromRequest->getAttribute('tokens', []), null, $secret); if (!$verifiedToken) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -192,17 +172,17 @@ $createSession = function (string $userId, string $secret, Request $request, Res $user->setAttributes($userFromRequest->getArrayCopy()); - $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; + $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); - $sessionSecret = $proofForToken->generate(); + $sessionSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION); $factor = (match ($verifiedToken->getAttribute('type')) { - TOKEN_TYPE_MAGIC_URL, - TOKEN_TYPE_OAUTH2, - TOKEN_TYPE_EMAIL => Type::EMAIL, - TOKEN_TYPE_PHONE => Type::PHONE, - TOKEN_TYPE_GENERIC => 'token', + Auth::TOKEN_TYPE_MAGIC_URL, + Auth::TOKEN_TYPE_OAUTH2, + Auth::TOKEN_TYPE_EMAIL => Type::EMAIL, + Auth::TOKEN_TYPE_PHONE => Type::PHONE, + Auth::TOKEN_TYPE_GENERIC => 'token', default => throw new Exception(Exception::USER_INVALID_TOKEN) }); @@ -212,7 +192,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), 'provider' => Auth::getSessionProviderByTokenType($verifiedToken->getAttribute('type')), - 'secret' => $proofForToken->hash($sessionSecret), // One way hash encryption to protect DB leak + 'secret' => Auth::hash($sessionSecret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), 'factors' => [$factor], @@ -237,11 +217,11 @@ $createSession = function (string $userId, string $secret, Request $request, Res $dbForProject->purgeCachedDocument('users', $user->getId()); // Magic URL + Email OTP - if ($verifiedToken->getAttribute('type') === TOKEN_TYPE_MAGIC_URL || $verifiedToken->getAttribute('type') === TOKEN_TYPE_EMAIL) { + if ($verifiedToken->getAttribute('type') === Auth::TOKEN_TYPE_MAGIC_URL || $verifiedToken->getAttribute('type') === Auth::TOKEN_TYPE_EMAIL) { $user->setAttribute('emailVerification', true); } - if ($verifiedToken->getAttribute('type') === TOKEN_TYPE_PHONE) { + if ($verifiedToken->getAttribute('type') === Auth::TOKEN_TYPE_PHONE) { $user->setAttribute('phoneVerification', true); } @@ -252,8 +232,8 @@ $createSession = function (string $userId, string $secret, Request $request, Res } $isAllowedTokenType = match ($verifiedToken->getAttribute('type')) { - TOKEN_TYPE_MAGIC_URL, - TOKEN_TYPE_EMAIL => false, + Auth::TOKEN_TYPE_MAGIC_URL, + Auth::TOKEN_TYPE_EMAIL => false, default => true }; @@ -273,21 +253,16 @@ $createSession = function (string $userId, string $secret, Request $request, Res ->setParam('userId', $user->getId()) ->setParam('sessionId', $session->getId()); - $encoded = $store - ->setProperty('id', $user->getId()) - ->setProperty('secret', $sessionSecret) - ->encode(); - if (!Config::getParam('domainVerification')) { - $response->addHeader('X-Fallback-Cookies', \json_encode([$store->getKey() => $encoded])); + $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $sessionSecret)])); } $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration)); $protocol = $request->getProtocol(); $response - ->addCookie($store->getKey() . '_legacy', $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) + ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $sessionSecret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $sessionSecret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ->setStatusCode(Response::STATUS_CODE_CREATED); $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); @@ -296,7 +271,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res ->setAttribute('current', true) ->setAttribute('countryName', $countryName) ->setAttribute('expire', $expire) - ->setAttribute('secret', $encoded) + ->setAttribute('secret', Auth::encodeSession($user->getId(), $sessionSecret)) ; $response->dynamic($session, Response::MODEL_SESSION); @@ -382,9 +357,7 @@ App::post('/v1/account') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, true]); $passwordHistory = $project->getAttribute('auths', [])['passwordHistory'] ?? 0; - $proof = new ProofsPassword(); - $hash = $proof->hash($password); - + $password = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS); try { $userId = $userId == 'unique()' ? ID::unique() : $userId; $user->setAttributes([ @@ -397,11 +370,11 @@ App::post('/v1/account') 'email' => $email, 'emailVerification' => false, 'status' => true, - 'password' => $hash, - 'passwordHistory' => $passwordHistory > 0 ? [$hash] : [], + 'password' => $password, + 'passwordHistory' => $passwordHistory > 0 ? [$password] : [], 'passwordUpdate' => DateTime::now(), - 'hash' => $proof->getHash()->getName(), - 'hashOptions' => $proof->getHash()->getOptions(), + 'hash' => Auth::DEFAULT_ALGO, + 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, 'registration' => DateTime::now(), 'reset' => false, 'name' => $name, @@ -553,17 +526,15 @@ App::get('/v1/account/sessions') ], contentType: ContentType::JSON, )) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') - ->inject('store') - ->inject('proofForToken') - ->action(function (bool $includeTotal, Response $response, Document $user, Locale $locale, Store $store, ProofsToken $proofForToken) { + ->inject('project') + ->action(function (Response $response, Document $user, Locale $locale, Document $project) { $sessions = $user->getAttribute('sessions', []); - $current = Auth::sessionVerify($sessions, $store->getProperty('secret', ''), $proofForToken); + $current = Auth::sessionVerify($sessions, Auth::$secret); foreach ($sessions as $key => $session) {/** @var Document $session */ $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); @@ -577,7 +548,7 @@ App::get('/v1/account/sessions') $response->dynamic(new Document([ 'sessions' => $sessions, - 'total' => $includeTotal ? count($sessions) : 0, + 'total' => count($sessions), ]), Response::MODEL_SESSION_LIST); }); @@ -610,9 +581,7 @@ App::delete('/v1/account/sessions') ->inject('locale') ->inject('queueForEvents') ->inject('queueForDeletes') - ->inject('store') - ->inject('proofForToken') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes, Store $store, ProofsToken $proofForToken) { + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes) { $protocol = $request->getProtocol(); $sessions = $user->getAttribute('sessions', []); @@ -628,13 +597,13 @@ App::delete('/v1/account/sessions') ->setAttribute('current', false) ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))); - if ($proofForToken->verify($store->getProperty('secret', ''), $session->getAttribute('secret'))) { + if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { $session->setAttribute('current', true); // If current session delete the cookies too $response - ->addCookie($store->getKey() . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')); + ->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')); // Use current session for events. $queueForEvents @@ -678,13 +647,12 @@ App::get('/v1/account/sessions/:sessionId') ->inject('response') ->inject('user') ->inject('locale') - ->inject('store') - ->inject('proofForToken') - ->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Store $store, ProofsToken $proofForToken) { + ->inject('project') + ->action(function (?string $sessionId, Response $response, Document $user, Locale $locale, Document $project) { $sessions = $user->getAttribute('sessions', []); $sessionId = ($sessionId === 'current') - ? Auth::sessionVerify($user->getAttribute('sessions'), $store->getProperty('secret', ''), $proofForToken) + ? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret) : $sessionId; foreach ($sessions as $session) {/** @var Document $session */ @@ -692,7 +660,7 @@ App::get('/v1/account/sessions/:sessionId') $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session - ->setAttribute('current', ($proofForToken->verify($store->getProperty('secret', ''), $session->getAttribute('secret')))) + ->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret))) ->setAttribute('countryName', $countryName) ->setAttribute('secret', $session->getAttribute('secret', '')) ; @@ -735,13 +703,12 @@ App::delete('/v1/account/sessions/:sessionId') ->inject('locale') ->inject('queueForEvents') ->inject('queueForDeletes') - ->inject('store') - ->inject('proofForToken') - ->action(function (?string $sessionId, ?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes, Store $store, ProofsToken $proofForToken) { + ->inject('project') + ->action(function (?string $sessionId, ?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Delete $queueForDeletes, Document $project) { $protocol = $request->getProtocol(); $sessionId = ($sessionId === 'current') - ? Auth::sessionVerify($user->getAttribute('sessions'), $store->getProperty('secret', ''), $proofForToken) + ? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret) : $sessionId; $sessions = $user->getAttribute('sessions', []); @@ -758,7 +725,7 @@ App::delete('/v1/account/sessions/:sessionId') $session->setAttribute('current', false); - if ($proofForToken->verify($store->getProperty('secret', ''), $session->getAttribute('secret'))) { // If current session delete the cookies too + if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too $session ->setAttribute('current', true) ->setAttribute('countryName', $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'))); @@ -768,8 +735,8 @@ App::delete('/v1/account/sessions/:sessionId') } $response - ->addCookie($store->getKey() . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')); + ->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')); } $dbForProject->purgeCachedDocument('users', $user->getId()); @@ -820,12 +787,10 @@ App::patch('/v1/account/sessions/:sessionId') ->inject('dbForProject') ->inject('project') ->inject('queueForEvents') - ->inject('store') - ->inject('proofForToken') - ->action(function (?string $sessionId, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Store $store, ProofsToken $proofForToken) { + ->action(function (?string $sessionId, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents) { $sessionId = ($sessionId === 'current') - ? Auth::sessionVerify($user->getAttribute('sessions'), $store->getProperty('secret', ''), $proofForToken) + ? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret) : $sessionId; $sessions = $user->getAttribute('sessions', []); @@ -842,7 +807,7 @@ App::patch('/v1/account/sessions/:sessionId') } // Extend session - $authDuration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; + $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $session->setAttribute('expire', DateTime::addSeconds(new \DateTime(), $authDuration)); // Refresh OAuth access token @@ -860,7 +825,7 @@ App::patch('/v1/account/sessions/:sessionId') $session ->setAttribute('providerAccessToken', $oauth2->getAccessToken('')) ->setAttribute('providerRefreshToken', $oauth2->getRefreshToken('')) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $oauth2->getAccessTokenExpiry(''))); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); } // Save changes @@ -914,10 +879,7 @@ App::post('/v1/account/sessions/email') ->inject('queueForEvents') ->inject('queueForMails') ->inject('hooks') - ->inject('store') - ->inject('proofForPassword') - ->inject('proofForToken') - ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks) { $email = \strtolower($email); $protocol = $request->getProtocol(); @@ -925,9 +887,7 @@ App::post('/v1/account/sessions/email') Query::equal('email', [$email]), ]); - $userProofForPassword = ProofsPassword::createHash($profile->getAttribute('hash', $proofForPassword->getHash()->getName()), $profile->getAttribute('hashOptions', $proofForPassword->getHash()->getOptions())); - - if ($profile->isEmpty() || empty($profile->getAttribute('passwordUpdate')) || !$userProofForPassword->verify($password, $profile->getAttribute('password'))) { + if ($profile->isEmpty() || empty($profile->getAttribute('passwordUpdate')) || !Auth::passwordVerify($password, $profile->getAttribute('password'), $profile->getAttribute('hash'), $profile->getAttribute('hashOptions'))) { throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -939,18 +899,18 @@ App::post('/v1/account/sessions/email') $hooks->trigger('passwordValidator', [$dbForProject, $project, $password, &$user, false]); - $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; + $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); - $secret = $proofForToken->generate(); + $secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION); $session = new Document(array_merge( [ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'provider' => SESSION_PROVIDER_EMAIL, + 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $email, - 'secret' => $proofForToken->hash($secret), // One way hash encryption to protect DB leak + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), 'factors' => ['password'], @@ -965,12 +925,11 @@ App::post('/v1/account/sessions/email') Authorization::setRole(Role::user($user->getId())->toString()); // Re-hash if not using recommended algo - if ($user->getAttribute('hash') !== $proofForPassword->getHash()->getName()) { - $proofForPasswordUpdated = new ProofsPassword(); + if ($user->getAttribute('hash') !== Auth::DEFAULT_ALGO) { $user - ->setAttribute('password', $proofForPasswordUpdated->hash($password)) - ->setAttribute('hash', $proofForPasswordUpdated->getHash()->getName()) - ->setAttribute('hashOptions', $proofForPasswordUpdated->getHash()->getOptions()); + ->setAttribute('password', Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS)) + ->setAttribute('hash', Auth::DEFAULT_ALGO) + ->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS); $dbForProject->updateDocument('users', $user->getId(), $user); } @@ -982,20 +941,17 @@ App::post('/v1/account/sessions/email') Permission::delete(Role::user($user->getId())), ])); - $encoded = $store - ->setProperty('id', $user->getId()) - ->setProperty('secret', $secret) - ->encode(); - if (!Config::getParam('domainVerification')) { - $response->addHeader('X-Fallback-Cookies', \json_encode([$store->getKey() => $encoded])); + $response + ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) + ; } $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration)); $response - ->addCookie($store->getKey() . '_legacy', $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) + ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ->setStatusCode(Response::STATUS_CODE_CREATED) ; @@ -1004,7 +960,7 @@ App::post('/v1/account/sessions/email') $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('secret', $encoded) + ->setAttribute('secret', Auth::encodeSession($user->getId(), $secret)) ; $queueForEvents @@ -1013,11 +969,9 @@ App::post('/v1/account/sessions/email') ; if ($project->getAttribute('auths', [])['sessionAlerts'] ?? false) { - if ( - $dbForProject->count('sessions', [ - Query::equal('userId', [$user->getId()]), - ]) !== 1 - ) { + if ($dbForProject->count('sessions', [ + Query::equal('userId', [$user->getId()]), + ]) !== 1) { sendSessionAlert($locale, $user, $project, $session, $queueForMails); } } @@ -1058,10 +1012,7 @@ App::post('/v1/account/sessions/anonymous') ->inject('dbForProject') ->inject('geodb') ->inject('queueForEvents') - ->inject('store') - ->inject('proofForPassword') - ->inject('proofForToken') - ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents) { $protocol = $request->getProtocol(); if ('console' === $project->getId()) { @@ -1090,8 +1041,8 @@ App::post('/v1/account/sessions/anonymous') 'emailVerification' => false, 'status' => true, 'password' => null, - 'hash' => $proofForPassword->getHash()->getName(), - 'hashOptions' => $proofForPassword->getHash()->getOptions(), + 'hash' => Auth::DEFAULT_ALGO, + 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, 'passwordUpdate' => null, 'registration' => DateTime::now(), 'reset' => false, @@ -1109,18 +1060,18 @@ App::post('/v1/account/sessions/anonymous') Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token - $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; + $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); - $secret = $proofForToken->generate(); + $secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION); $session = new Document(array_merge( [ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'provider' => SESSION_PROVIDER_ANONYMOUS, - 'secret' => $proofForToken->hash($secret), // One way hash encryption to protect DB leak + 'provider' => Auth::SESSION_PROVIDER_ANONYMOUS, + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), 'factors' => ['anonymous'], @@ -1134,7 +1085,7 @@ App::post('/v1/account/sessions/anonymous') Authorization::setRole(Role::user($user->getId())->toString()); - $session = $dbForProject->createDocument('sessions', $session->setAttribute('$permissions', [ + $session = $dbForProject->createDocument('sessions', $session-> setAttribute('$permissions', [ Permission::read(Role::user($user->getId())), Permission::update(Role::user($user->getId())), Permission::delete(Role::user($user->getId())), @@ -1147,20 +1098,15 @@ App::post('/v1/account/sessions/anonymous') ->setParam('sessionId', $session->getId()) ; - $encoded = $store - ->setProperty('id', $user->getId()) - ->setProperty('secret', $secret) - ->encode(); - if (!Config::getParam('domainVerification')) { - $response->addHeader('X-Fallback-Cookies', \json_encode([$store->getKey() => $encoded])); + $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration)); $response - ->addCookie($store->getKey() . '_legacy', $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) + ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ->setStatusCode(Response::STATUS_CODE_CREATED) ; @@ -1169,7 +1115,7 @@ App::post('/v1/account/sessions/anonymous') $session ->setAttribute('current', true) ->setAttribute('countryName', $countryName) - ->setAttribute('secret', $encoded) + ->setAttribute('secret', Auth::encodeSession($user->getId(), $secret)) ; $response->dynamic($session, Response::MODEL_SESSION); @@ -1210,9 +1156,6 @@ App::post('/v1/account/sessions/token') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('store') - ->inject('proofForToken') - ->inject('proofForCode') ->action($createSession); App::get('/v1/account/sessions/oauth2/:provider') @@ -1405,10 +1348,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') ->inject('dbForProject') ->inject('geodb') ->inject('queueForEvents') - ->inject('store') - ->inject('proofForPassword') - ->inject('proofForToken') - ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, array $platforms, Document $devKey, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) use ($oauthDefaultSuccess) { + ->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, array $platforms, Document $devKey, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents) use ($oauthDefaultSuccess) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; $port = $request->getPort(); $callbackBase = $protocol . '://' . $request->getHostname(); @@ -1552,7 +1492,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } $sessions = $user->getAttribute('sessions', []); - $current = Auth::sessionVerify($sessions, $store->getProperty('secret', ''), $proofForToken); + $current = Auth::sessionVerify($sessions, Auth::$secret); if ($current) { // Delete current session of new one. $currentDocument = $dbForProject->getDocument('sessions', $current); @@ -1582,22 +1522,22 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') */ $isVerified = $oauth2->isEmailVerified($accessToken); - $identity = $dbForProject->findOne('identities', [ - Query::equal('provider', [$provider]), - Query::equal('providerUid', [$oauth2ID]), + $userWithEmail = $dbForProject->findOne('users', [ + Query::equal('email', [$email]), ]); - - if (!$identity->isEmpty()) { - $user = $dbForProject->getDocument('users', $identity->getAttribute('userId')); + if (!$userWithEmail->isEmpty()) { + $user->setAttributes($userWithEmail->getArrayCopy()); } // If user is not found, check if there is an identity with the same provider user ID if ($user === false || $user->isEmpty()) { - $userWithEmail = $dbForProject->findOne('users', [ - Query::equal('email', [$email]), + $identity = $dbForProject->findOne('identities', [ + Query::equal('provider', [$provider]), + Query::equal('providerUid', [$oauth2ID]), ]); - if (!$userWithEmail->isEmpty()) { - $user->setAttributes($userWithEmail->getArrayCopy()); + + if (!$identity->isEmpty()) { + $user = $dbForProject->getDocument('users', $identity->getAttribute('userId')); } } @@ -1633,8 +1573,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'emailVerification' => true, 'status' => true, // Email should already be authenticated by OAuth2 provider 'password' => null, - 'hash' => $proofForPassword->getHash()->getName(), - 'hashOptions' => $proofForPassword->getHash()->getOptions(), + 'hash' => Auth::DEFAULT_ALGO, + 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, 'passwordUpdate' => null, 'registration' => DateTime::now(), 'reset' => false, @@ -1706,13 +1646,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'providerEmail' => $email, 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry), + 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), ])); } else { $identity ->setAttribute('providerAccessToken', $accessToken) ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry)); + ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); $dbForProject->updateDocument('identities', $identity->getId(), $identity); } @@ -1733,19 +1673,18 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $state['success'] = URLParser::parse($state['success']); $query = URLParser::parseQuery($state['success']['query']); - $duration = $project->getAttribute('auths', [])['duration'] ?? TOKEN_EXPIRATION_LOGIN_LONG; + $duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration)); - $proofsForTokenOAuth2 = new ProofsToken(TOKEN_LENGTH_OAUTH2); // If the `token` param is set, we will return the token in the query string if ($state['token']) { - $secret = $proofsForTokenOAuth2->generate(); + $secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_OAUTH2); $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'type' => TOKEN_TYPE_OAUTH2, - 'secret' => $proofsForTokenOAuth2->hash($secret), // One way hash encryption to protect DB leak + 'type' => Auth::TOKEN_TYPE_OAUTH2, + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -1773,7 +1712,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } else { $detector = new Detector($request->getUserAgent('UNKNOWN')); $record = $geodb->get($request->getIP()); - $secret = $proofForToken->generate(); + $secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION); $session = new Document(array_merge([ '$id' => ID::unique(), @@ -1784,7 +1723,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'providerAccessToken' => $accessToken, 'providerRefreshToken' => $refreshToken, 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), - 'secret' => $proofForToken->hash($secret), // One way hash encryption to protect DB leak + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), 'factors' => [TYPE::EMAIL, 'oauth2'], // include a special oauth2 factor to bypass MFA checks @@ -1800,13 +1739,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $session->setAttribute('expire', $expire); - $encoded = $store - ->setProperty('id', $user->getId()) - ->setProperty('secret', $secret) - ->encode(); - if (!Config::getParam('domainVerification')) { - $response->addHeader('X-Fallback-Cookies', \json_encode([$store->getKey() => $encoded])); + $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); } $queueForEvents @@ -1819,13 +1753,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') if ($state['success']['path'] == $oauthDefaultSuccess) { $query['project'] = $project->getId(); $query['domain'] = Config::getParam('cookieDomain'); - $query['key'] = $store->getKey(); - $query['secret'] = $encoded; + $query['key'] = Auth::$cookieName; + $query['secret'] = Auth::encodeSession($user->getId(), $secret); } $response - ->addCookie($store->getKey() . '_legacy', $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), $encoded, (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')); + ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')); } if (isset($sessionUpgrade) && $sessionUpgrade) { @@ -1983,8 +1917,7 @@ App::post('/v1/account/tokens/magic-url') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('proofForPassword') - ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword) { + ->action(function (string $userId, string $email, string $url, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2030,8 +1963,8 @@ App::post('/v1/account/tokens/magic-url') 'emailVerification' => false, 'status' => true, 'password' => null, - 'hash' => $proofForPassword->getHash()->getName(), - 'hashOptions' => $proofForPassword->getHash()->getOptions(), + 'hash' => Auth::DEFAULT_ALGO, + 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, 'passwordUpdate' => null, 'registration' => DateTime::now(), 'reset' => false, @@ -2049,18 +1982,15 @@ App::post('/v1/account/tokens/magic-url') Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } - $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); - $proofForToken->setHash(new Sha()); - - $tokenSecret = $proofForToken->generate(); - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_CONFIRM)); + $tokenSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_MAGIC_URL); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM)); $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'type' => TOKEN_TYPE_MAGIC_URL, - 'secret' => $proofForToken->hash($tokenSecret), // One way hash encryption to protect DB leak + 'type' => Auth::TOKEN_TYPE_MAGIC_URL, + 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -2095,7 +2025,6 @@ App::post('/v1/account/tokens/magic-url') $url = Template::unParseURL($url); $subject = $locale->getText("emails.magicSession.subject"); - $preview = $locale->getText("emails.magicSession.preview"); $customTemplate = $project->getAttribute('templates', [])['email.magicSession-' . $locale->default] ?? []; $detector = new Detector($request->getUserAgent('UNKNOWN')); @@ -2184,7 +2113,6 @@ App::post('/v1/account/tokens/magic-url') $queueForMails ->setSubject($subject) - ->setPreview($preview) ->setBody($body) ->setVariables($emailVariables) ->setRecipient($email) @@ -2239,9 +2167,7 @@ App::post('/v1/account/tokens/email') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('proofForPassword') - ->inject('proofForCode') - ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsPassword $proofForPassword, ProofsCode $proofForCode) { + ->action(function (string $userId, string $email, bool $phrase, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled'); } @@ -2285,8 +2211,8 @@ App::post('/v1/account/tokens/email') 'emailVerification' => false, 'status' => true, 'password' => null, - 'hash' => $proofForPassword->getHash()->getName(), - 'hashOptions' => $proofForPassword->getHash()->getOptions(), + 'hash' => Auth::DEFAULT_ALGO, + 'hashOptions' => Auth::DEFAULT_ALGO_OPTIONS, 'passwordUpdate' => null, 'registration' => DateTime::now(), 'reset' => false, @@ -2299,41 +2225,18 @@ App::post('/v1/account/tokens/email') ]); $user->removeAttribute('$sequence'); - $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); - try { - $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ - '$permissions' => [ - Permission::read(Role::user($user->getId())), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), - 'providerType' => MESSAGE_TYPE_EMAIL, - 'identifier' => $email, - ]))); - $user->setAttribute('targets', [...$user->getAttribute('targets', []), $target]); - } catch (Duplicate) { - $existingTarget = $dbForProject->findOne('targets', [ - Query::equal('identifier', [$email]), - ]); - if (!$existingTarget->isEmpty()) { - $user->setAttribute('targets', $existingTarget, Document::SET_TYPE_APPEND); - } - } - - $dbForProject->purgeCachedDocument('users', $user->getId()); + Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } - $tokenSecret = $proofForCode->generate(); - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_OTP)); + $tokenSecret = Auth::codeGenerator(6); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_OTP)); $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'type' => TOKEN_TYPE_EMAIL, - 'secret' => $proofForCode->hash($tokenSecret), // One way hash encryption to protect DB leak + 'type' => Auth::TOKEN_TYPE_EMAIL, + 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -2351,18 +2254,7 @@ App::post('/v1/account/tokens/email') $dbForProject->purgeCachedDocument('users', $user->getId()); $subject = $locale->getText("emails.otpSession.subject"); - $preview = $locale->getText("emails.otpSession.preview"); - $heading = $locale->getText("emails.otpSession.heading"); - $customTemplate = $project->getAttribute('templates', [])['email.otpSession-' . $locale->default] ?? []; - $smtpBaseTemplate = $project->getAttribute('smtpBaseTemplate', 'email-base'); - - $validator = new FileName(); - if (!$validator->isValid($smtpBaseTemplate)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid template path'); - } - - $bodyTemplate = __DIR__ . '/../../config/locale/templates/' . $smtpBaseTemplate . '.tpl'; $detector = new Detector($request->getUserAgent('UNKNOWN')); $agentOs = $detector->getOS(); @@ -2432,7 +2324,6 @@ App::post('/v1/account/tokens/email') } $emailVariables = [ - 'heading' => $heading, 'direction' => $locale->getText('settings.direction'), // {{user}}, {{project}} and {{otp}} are required in the templates 'user' => $user->getAttribute('name'), @@ -2446,23 +2337,9 @@ App::post('/v1/account/tokens/email') 'team' => '', ]; - if ($smtpBaseTemplate === APP_BRANDED_EMAIL_BASE_TEMPLATE) { - $emailVariables = array_merge($emailVariables, [ - 'accentColor' => APP_EMAIL_ACCENT_COLOR, - 'logoUrl' => APP_EMAIL_LOGO_URL, - 'twitterUrl' => APP_SOCIAL_TWITTER, - 'discordUrl' => APP_SOCIAL_DISCORD, - 'githubUrl' => APP_SOCIAL_GITHUB_APPWRITE, - 'termsUrl' => APP_EMAIL_TERMS_URL, - 'privacyUrl' => APP_EMAIL_PRIVACY_URL, - ]); - } - $queueForMails ->setSubject($subject) - ->setPreview($preview) ->setBody($body) - ->setBodyTemplate($bodyTemplate) ->setVariables($emailVariables) ->setRecipient($email) ->trigger(); @@ -2502,10 +2379,7 @@ App::put('/v1/account/sessions/magic-url') ) ], contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.6.0', - replaceWith: 'account.createSession' - ), + deprecated: true, )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') @@ -2520,13 +2394,7 @@ App::put('/v1/account/sessions/magic-url') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('store') - ->inject('proofForCode') - ->action(function ($userId, $secret, $request, $response, $user, $dbForProject, $project, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForCode) use ($createSession) { - $proofForToken = new ProofsToken(TOKEN_LENGTH_MAGIC_URL); - $proofForToken->setHash(new Sha()); - $createSession($userId, $secret, $request, $response, $user, $dbForProject, $project, $locale, $geodb, $queueForEvents, $queueForMails, $store, $proofForToken, $proofForCode); - }); + ->action($createSession); App::put('/v1/account/sessions/phone') ->desc('Update phone session') @@ -2549,10 +2417,7 @@ App::put('/v1/account/sessions/phone') ) ], contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.6.0', - replaceWith: 'account.createSession' - ), + deprecated: true, )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') @@ -2567,9 +2432,6 @@ App::put('/v1/account/sessions/phone') ->inject('geodb') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('store') - ->inject('proofForToken') - ->inject('proofForCode') ->action($createSession); App::post('/v1/account/tokens/phone') @@ -2610,9 +2472,7 @@ App::post('/v1/account/tokens/phone') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('store') - ->inject('proofForCode') - ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, Store $store, ProofsCode $proofForCode) { + ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2691,15 +2551,15 @@ App::post('/v1/account/tokens/phone') } } - $secret ??= $proofForCode->generate(); - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_OTP)); + $secret ??= Auth::codeGenerator(); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_OTP)); $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'type' => TOKEN_TYPE_PHONE, - 'secret' => $proofForCode->hash($secret), + 'type' => Auth::TOKEN_TYPE_PHONE, + 'secret' => Auth::hash($secret), 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -2774,11 +2634,7 @@ App::post('/v1/account/tokens/phone') ->setPayload($response->output($token, Response::MODEL_TOKEN), sensitive: ['secret']); // Encode secret for clients - $encoded = $store - ->setProperty('id', $user->getId()) - ->setProperty('secret', $secret) - ->encode(); - $token->setAttribute('secret', $encoded); + $token->setAttribute('secret', Auth::encodeSession($user->getId(), $secret)); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -2809,16 +2665,20 @@ App::post('/v1/account/jwts') ->label('abuse-key', 'url:{url},userId:{userId}') ->inject('response') ->inject('user') - ->inject('store') - ->inject('proofForToken') - ->action(function (Response $response, Document $user, Store $store, ProofsToken $proofForToken) { + ->inject('dbForProject') + ->action(function (Response $response, Document $user, Database $dbForProject) { $sessions = $user->getAttribute('sessions', []); + $current = new Document(); - $sessionId = Auth::sessionVerify($sessions, $store->getProperty('secret', ''), $proofForToken); + foreach ($sessions as $session) { /** @var Utopia\Database\Document $session */ + if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too + $current = $session; + } + } - if (!$sessionId) { + if ($current->isEmpty()) { throw new Exception(Exception::USER_SESSION_NOT_FOUND); } @@ -2826,12 +2686,10 @@ App::post('/v1/account/jwts') $response ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic(new Document([ - 'jwt' => $jwt->encode([ - 'userId' => $user->getId(), - 'sessionId' => $sessionId, - ]) - ]), Response::MODEL_JWT); + ->dynamic(new Document(['jwt' => $jwt->encode([ + 'userId' => $user->getId(), + 'sessionId' => $current->getId(), + ])]), Response::MODEL_JWT); }); App::get('/v1/account/prefs') @@ -2880,13 +2738,12 @@ App::get('/v1/account/logs') contentType: ContentType::JSON, )) ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') ->inject('geodb') ->inject('dbForProject') - ->action(function (array $queries, bool $includeTotal, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { + ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -2931,7 +2788,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $includeTotal ? $audit->countLogsByUser($user->getSequence(), $queries) : 0, + 'total' => $audit->countLogsByUser($user->getSequence(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -3006,23 +2863,18 @@ App::patch('/v1/account/password') ->inject('dbForProject') ->inject('queueForEvents') ->inject('hooks') - ->inject('store') - ->inject('proofForPassword') - ->inject('proofForToken') - ->action(function (string $password, string $oldPassword, ?\DateTime $requestTimestamp, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Hooks $hooks, Store $store, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { - $userProofForPassword = ProofsPassword::createHash($user->getAttribute('hash'), $user->getAttribute('hashOptions')); + ->action(function (string $password, string $oldPassword, ?\DateTime $requestTimestamp, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Hooks $hooks) { + // Check old password only if its an existing user. - if (!empty($user->getAttribute('passwordUpdate')) && !$userProofForPassword->verify($oldPassword, $user->getAttribute('password'))) { // Double check user password + if (!empty($user->getAttribute('passwordUpdate')) && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions'))) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } - $newPassword = $proofForPassword->hash($password); + $newPassword = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS); $historyLimit = $project->getAttribute('auths', [])['passwordHistory'] ?? 0; - $hash = ProofsPassword::createHash($user->getAttribute('hash'), $user->getAttribute('hashOptions')); $history = $user->getAttribute('passwordHistory', []); - if ($historyLimit > 0) { - $validator = new PasswordHistory($history, $hash); + $validator = new PasswordHistory($history, $user->getAttribute('hash'), $user->getAttribute('hashOptions')); if (!$validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -3044,22 +2896,8 @@ App::patch('/v1/account/password') ->setAttribute('password', $newPassword) ->setAttribute('passwordHistory', $history) ->setAttribute('passwordUpdate', DateTime::now()) - ->setAttribute('hash', $proofForPassword->getHash()->getName()) - ->setAttribute('hashOptions', $proofForPassword->getHash()->getOptions()); - - $sessions = $user->getAttribute('sessions', []); - - $current = Auth::sessionVerify($sessions, $store->getProperty('secret', ''), $proofForToken); - - $invalidate = $project->getAttribute('auths', default: [])['invalidateSessions'] ?? false; - if ($invalidate && !empty($current)) { - foreach ($sessions as $session) { - /** @var Document $session */ - if ($session->getId() !== $current) { - $dbForProject->deleteDocument('sessions', $session->getId()); - } - } - } + ->setAttribute('hash', Auth::DEFAULT_ALGO) + ->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS); $user = $dbForProject->updateDocument('users', $user->getId(), $user); @@ -3098,16 +2936,13 @@ App::patch('/v1/account/email') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') - ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->action(function (string $email, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); - $userProofForPassword = ProofsPassword::createHash($user->getAttribute('hash'), $user->getAttribute('hashOptions')); - if ( !empty($passwordUpdate) && - !$userProofForPassword->verify($password, $user->getAttribute('password')) + !Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) ) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -3134,9 +2969,9 @@ App::patch('/v1/account/email') if (empty($passwordUpdate)) { $user - ->setAttribute('password', $proofForPassword->hash($password)) - ->setAttribute('hash', $proofForPassword->getHash()->getName()) - ->setAttribute('hashOptions', $proofForPassword->getHash()->getOptions()) + ->setAttribute('password', Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS)) + ->setAttribute('hash', Auth::DEFAULT_ALGO) + ->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS) ->setAttribute('passwordUpdate', DateTime::now()); } @@ -3198,16 +3033,13 @@ App::patch('/v1/account/phone') ->inject('queueForEvents') ->inject('project') ->inject('hooks') - ->inject('proofForPassword') - ->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks, ProofsPassword $proofForPassword) { + ->action(function (string $phone, string $password, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Document $project, Hooks $hooks) { // passwordUpdate will be empty if the user has never set a password $passwordUpdate = $user->getAttribute('passwordUpdate'); - $userProofForPassword = ProofsPassword::createHash($user->getAttribute('hash'), $user->getAttribute('hashOptions')); - if ( !empty($passwordUpdate) && - !$userProofForPassword->verify($password, $user->getAttribute('password')) + !Auth::passwordVerify($password, $user->getAttribute('password'), $user->getAttribute('hash'), $user->getAttribute('hashOptions')) ) { // Double check user password throw new Exception(Exception::USER_INVALID_CREDENTIALS); } @@ -3231,9 +3063,9 @@ App::patch('/v1/account/phone') if (empty($passwordUpdate)) { $user - ->setAttribute('password', $proofForPassword->hash($password)) - ->setAttribute('hash', $proofForPassword->getHash()->getName()) - ->setAttribute('hashOptions', $proofForPassword->getHash()->getOptions()) + ->setAttribute('password', Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS)) + ->setAttribute('hash', Auth::DEFAULT_ALGO) + ->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS) ->setAttribute('passwordUpdate', DateTime::now()); } @@ -3278,7 +3110,7 @@ App::patch('/v1/account/prefs') ], contentType: ContentType::JSON )) - ->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.', example: '{"language":"en","timezone":"UTC","darkTheme":true}') + ->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.') ->inject('requestTimestamp') ->inject('response') ->inject('user') @@ -3322,8 +3154,7 @@ App::patch('/v1/account/status') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('store') - ->action(function (?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Store $store) { + ->action(function (?\DateTime $requestTimestamp, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { $user->setAttribute('status', false); @@ -3339,8 +3170,8 @@ App::patch('/v1/account/status') $protocol = $request->getProtocol(); $response - ->addCookie($store->getKey() . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie($store->getKey(), '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) + ->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) + ->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) ; $response->dynamic($user, Response::MODEL_ACCOUNT); @@ -3380,8 +3211,7 @@ App::post('/v1/account/recovery') ->inject('locale') ->inject('queueForMails') ->inject('queueForEvents') - ->inject('proofForToken') - ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents, ProofsToken $proofForToken) { + ->action(function (string $email, string $url, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Mail $queueForMails, Event $queueForEvents) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); @@ -3403,15 +3233,15 @@ App::post('/v1/account/recovery') throw new Exception(Exception::USER_BLOCKED); } - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_RECOVERY)); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_RECOVERY)); - $secret = $proofForToken->generate(); + $secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_RECOVERY); $recovery = new Document([ '$id' => ID::unique(), 'userId' => $profile->getId(), 'userInternalId' => $profile->getSequence(), - 'type' => TOKEN_TYPE_RECOVERY, - 'secret' => $proofForToken->hash($secret), // One way hash encryption to protect DB leak + 'type' => Auth::TOKEN_TYPE_RECOVERY, + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -3435,7 +3265,6 @@ App::post('/v1/account/recovery') $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $body = $locale->getText("emails.recovery.body"); $subject = $locale->getText("emails.recovery.subject"); - $preview = $locale->getText("emails.recovery.preview"); $customTemplate = $project->getAttribute('templates', [])['email.recovery-' . $locale->default] ?? []; $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl'); @@ -3510,7 +3339,6 @@ App::post('/v1/account/recovery') ->setBody($body) ->setVariables($emailVariables) ->setSubject($subject) - ->setPreview($preview) ->trigger(); $recovery->setAttribute('secret', $secret); @@ -3559,9 +3387,7 @@ App::put('/v1/account/recovery') ->inject('project') ->inject('queueForEvents') ->inject('hooks') - ->inject('proofForPassword') - ->inject('proofForToken') - ->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks, ProofsPassword $proofForPassword, ProofsToken $proofForToken) { + ->action(function (string $userId, string $secret, string $password, Response $response, Document $user, Database $dbForProject, Document $project, Event $queueForEvents, Hooks $hooks) { $profile = $dbForProject->getDocument('users', $userId); if ($profile->isEmpty()) { @@ -3569,7 +3395,7 @@ App::put('/v1/account/recovery') } $tokens = $profile->getAttribute('tokens', []); - $verifiedToken = Auth::tokenVerify($tokens, TOKEN_TYPE_RECOVERY, $secret, $proofForToken); + $verifiedToken = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_RECOVERY, $secret); if (!$verifiedToken) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -3577,14 +3403,12 @@ App::put('/v1/account/recovery') Authorization::setRole(Role::user($profile->getId())->toString()); - $newPassword = $proofForPassword->hash($password); + $newPassword = Auth::passwordHash($password, Auth::DEFAULT_ALGO, Auth::DEFAULT_ALGO_OPTIONS); - $hash = ProofsPassword::createHash($profile->getAttribute('hash'), $profile->getAttribute('hashOptions')); $historyLimit = $project->getAttribute('auths', [])['passwordHistory'] ?? 0; $history = $profile->getAttribute('passwordHistory', []); - if ($historyLimit > 0) { - $validator = new PasswordHistory($history, $hash); + $validator = new PasswordHistory($history, $profile->getAttribute('hash'), $profile->getAttribute('hashOptions')); if (!$validator->isValid($password)) { throw new Exception(Exception::USER_PASSWORD_RECENTLY_USED); } @@ -3599,8 +3423,8 @@ App::put('/v1/account/recovery') ->setAttribute('password', $newPassword) ->setAttribute('passwordHistory', $history) ->setAttribute('passwordUpdate', DateTime::now()) - ->setAttribute('hash', $proofForPassword->getHash()->getName()) - ->setAttribute('hashOptions', $proofForPassword->getHash()->getOptions()) + ->setAttribute('hash', Auth::DEFAULT_ALGO) + ->setAttribute('hashOptions', Auth::DEFAULT_ALGO_OPTIONS) ->setAttribute('emailVerification', true)); $user->setAttributes($profile->getArrayCopy()); @@ -3622,48 +3446,27 @@ App::put('/v1/account/recovery') $response->dynamic($recoveryDocument, Response::MODEL_TOKEN); }); -App::post('/v1/account/verifications/email') - ->alias('/v1/account/verification') +App::post('/v1/account/verification') ->desc('Create email verification') ->groups(['api', 'account']) ->label('scope', 'account') ->label('event', 'users.[userId].verification.[tokenId].create') ->label('audits.event', 'verification.create') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'verification', - name: 'createEmailVerification', - description: '/docs/references/account/create-email-verification.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_TOKEN, - ) - ], - contentType: ContentType::JSON, - ), - new Method( - namespace: 'account', - group: 'verification', - name: 'createVerification', - description: '/docs/references/account/create-email-verification.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_TOKEN, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.createEmailVerification' - ), - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'verification', + name: 'createVerification', + description: '/docs/references/account/create-email-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') ->param('url', '', fn ($platforms, $devKey) => $devKey->isEmpty() ? new Redirect($platforms) : new URL(), 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', false, ['platforms', 'devKey']) // TODO add built-in confirm page @@ -3675,31 +3478,26 @@ App::post('/v1/account/verifications/email') ->inject('locale') ->inject('queueForEvents') ->inject('queueForMails') - ->inject('proofForToken') - ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails, ProofsToken $proofForToken) { + ->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Event $queueForEvents, Mail $queueForMails) { if (empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled'); } - if (empty($user->getAttribute('email'))) { - throw new Exception(Exception::USER_EMAIL_NOT_FOUND); - } - $url = htmlentities($url); if ($user->getAttribute('emailVerification')) { throw new Exception(Exception::USER_EMAIL_ALREADY_VERIFIED); } - $verificationSecret = $proofForToken->generate(); - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_CONFIRM)); + $verificationSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_VERIFICATION); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM)); $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'type' => TOKEN_TYPE_VERIFICATION, - 'secret' => $proofForToken->hash($verificationSecret), // One way hash encryption to protect DB leak + 'type' => Auth::TOKEN_TYPE_VERIFICATION, + 'secret' => Auth::hash($verificationSecret), // One way hash encryption to protect DB leak 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -3722,19 +3520,8 @@ App::post('/v1/account/verifications/email') $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); $body = $locale->getText("emails.verification.body"); - $preview = $locale->getText("emails.verification.preview"); $subject = $locale->getText("emails.verification.subject"); - $heading = $locale->getText("emails.verification.heading"); - $customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? []; - $smtpBaseTemplate = $project->getAttribute('smtpBaseTemplate', 'email-base'); - - $validator = new FileName(); - if (!$validator->isValid($smtpBaseTemplate)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid template path'); - } - - $bodyTemplate = __DIR__ . '/../../config/locale/templates/' . $smtpBaseTemplate . '.tpl'; $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl'); $message @@ -3794,7 +3581,6 @@ App::post('/v1/account/verifications/email') } $emailVariables = [ - 'heading' => $heading, 'direction' => $locale->getText('settings.direction'), // {{user}}, {{redirect}} and {{project}} are required in default and custom templates 'user' => $user->getAttribute('name'), @@ -3804,23 +3590,9 @@ App::post('/v1/account/verifications/email') 'team' => '', ]; - if ($smtpBaseTemplate === APP_BRANDED_EMAIL_BASE_TEMPLATE) { - $emailVariables = array_merge($emailVariables, [ - 'accentColor' => APP_EMAIL_ACCENT_COLOR, - 'logoUrl' => APP_EMAIL_LOGO_URL, - 'twitterUrl' => APP_SOCIAL_TWITTER, - 'discordUrl' => APP_SOCIAL_DISCORD, - 'githubUrl' => APP_SOCIAL_GITHUB_APPWRITE, - 'termsUrl' => APP_EMAIL_TERMS_URL, - 'privacyUrl' => APP_EMAIL_PRIVACY_URL, - ]); - } - $queueForMails ->setSubject($subject) - ->setPreview($preview) ->setBody($body) - ->setBodyTemplate($bodyTemplate) ->setVariables($emailVariables) ->setRecipient($user->getAttribute('email')) ->setName($user->getAttribute('name') ?? '') @@ -3838,48 +3610,27 @@ App::post('/v1/account/verifications/email') ->dynamic($verification, Response::MODEL_TOKEN); }); -App::put('/v1/account/verifications/email') - ->alias('/v1/account/verification') +App::put('/v1/account/verification') ->desc('Update email verification (confirmation)') ->groups(['api', 'account']) ->label('scope', 'public') ->label('event', 'users.[userId].verification.[tokenId].update') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'verification', - name: 'updateEmailVerification', - description: '/docs/references/account/update-email-verification.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_TOKEN, - ) - ], - contentType: ContentType::JSON - ), - new Method( - namespace: 'account', - group: 'verification', - name: 'updateVerification', - description: '/docs/references/account/update-email-verification.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_TOKEN, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.updateEmailVerification' - ), - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'verification', + name: 'updateVerification', + description: '/docs/references/account/update-email-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3888,8 +3639,7 @@ App::put('/v1/account/verifications/email') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('proofForToken') - ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, ProofsToken $proofForToken) { + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); @@ -3898,7 +3648,7 @@ App::put('/v1/account/verifications/email') } $tokens = $profile->getAttribute('tokens', []); - $verifiedToken = Auth::tokenVerify($tokens, TOKEN_TYPE_VERIFICATION, $secret, $proofForToken); + $verifiedToken = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_VERIFICATION, $secret); if (!$verifiedToken) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -3927,8 +3677,7 @@ App::put('/v1/account/verifications/email') $response->dynamic($verification, Response::MODEL_TOKEN); }); -App::post('/v1/account/verifications/phone') - ->alias('/v1/account/verification/phone') +App::post('/v1/account/verification/phone') ->desc('Create phone verification') ->groups(['api', 'account', 'auth']) ->label('scope', 'account') @@ -3963,8 +3712,7 @@ App::post('/v1/account/verifications/phone') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('proofForCode') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsCode $proofForCode) { + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -3989,15 +3737,15 @@ App::post('/v1/account/verifications/phone') } } - $secret ??= $proofForCode->generate(); - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_CONFIRM)); + $secret ??= Auth::codeGenerator(); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM)); $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), - 'type' => TOKEN_TYPE_PHONE, - 'secret' => $proofForCode->hash($secret), + 'type' => Auth::TOKEN_TYPE_PHONE, + 'secret' => Auth::hash($secret), 'expire' => $expire, 'userAgent' => $request->getUserAgent('UNKNOWN'), 'ip' => $request->getIP(), @@ -4078,8 +3826,7 @@ App::post('/v1/account/verifications/phone') ->dynamic($verification, Response::MODEL_TOKEN); }); -App::put('/v1/account/verifications/phone') - ->alias('/v1/account/verification/phone') +App::put('/v1/account/verification/phone') ->desc('Update phone verification (confirmation)') ->groups(['api', 'account']) ->label('scope', 'public') @@ -4108,8 +3855,7 @@ App::put('/v1/account/verifications/phone') ->inject('user') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('proofForCode') - ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, ProofsCode $proofForCode) { + ->action(function (string $userId, string $secret, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { $profile = Authorization::skip(fn () => $dbForProject->getDocument('users', $userId)); @@ -4117,7 +3863,7 @@ App::put('/v1/account/verifications/phone') throw new Exception(Exception::USER_NOT_FOUND); } - $verifiedToken = Auth::tokenVerify($user->getAttribute('tokens', []), TOKEN_TYPE_PHONE, $secret, $proofForCode); + $verifiedToken = Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_PHONE, $secret); if (!$verifiedToken) { throw new Exception(Exception::USER_INVALID_TOKEN); @@ -4207,40 +3953,20 @@ App::get('/v1/account/mfa/factors') ->desc('List factors') ->groups(['api', 'account', 'mfa']) ->label('scope', 'account') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'listMfaFactors', - description: '/docs/references/account/list-mfa-factors.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_FACTORS, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.listMFAFactors', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'listMFAFactors', - description: '/docs/references/account/list-mfa-factors.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_FACTORS, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'listMfaFactors', + description: '/docs/references/account/list-mfa-factors.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_FACTORS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -4268,40 +3994,20 @@ App::post('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'createMfaAuthenticator', - description: '/docs/references/account/create-mfa-authenticator.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_TYPE, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.createMFAAuthenticator', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'createMFAAuthenticator', - description: '/docs/references/account/create-mfa-authenticator.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_TYPE, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'createMfaAuthenticator', + description: '/docs/references/account/create-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_TYPE, + ) + ], + contentType: ContentType::JSON + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator. Must be `' . Type::TOTP . '`') ->inject('requestTimestamp') ->inject('response') @@ -4365,40 +4071,20 @@ App::put('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'updateMfaAuthenticator', - description: '/docs/references/account/update-mfa-authenticator.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_USER, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.updateMFAAuthenticator', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'updateMFAAuthenticator', - description: '/docs/references/account/update-mfa-authenticator.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_USER, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'updateMfaAuthenticator', + description: '/docs/references/account/update-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->param('otp', '', new Text(256), 'Valid verification token.') ->inject('response') @@ -4455,40 +4141,20 @@ App::post('/v1/account/mfa/recovery-codes') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'createMfaRecoveryCodes', - description: '/docs/references/account/create-mfa-recovery-codes.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_MFA_RECOVERY_CODES, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.createMFARecoveryCodes', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'createMFARecoveryCodes', - description: '/docs/references/account/create-mfa-recovery-codes.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_MFA_RECOVERY_CODES, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'createMfaRecoveryCodes', + description: '/docs/references/account/create-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->inject('dbForProject') @@ -4522,40 +4188,20 @@ App::patch('/v1/account/mfa/recovery-codes') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'updateMfaRecoveryCodes', - description: '/docs/references/account/update-mfa-recovery-codes.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_RECOVERY_CODES, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.updateMFARecoveryCodes', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'updateMFARecoveryCodes', - description: '/docs/references/account/update-mfa-recovery-codes.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_RECOVERY_CODES, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'updateMfaRecoveryCodes', + description: '/docs/references/account/update-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('dbForProject') ->inject('response') ->inject('user') @@ -4584,40 +4230,20 @@ App::get('/v1/account/mfa/recovery-codes') ->desc('List MFA recovery codes') ->groups(['api', 'account', 'mfaProtected']) ->label('scope', 'account') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'getMfaRecoveryCodes', - description: '/docs/references/account/get-mfa-recovery-codes.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_RECOVERY_CODES, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.getMFARecoveryCodes', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'getMFARecoveryCodes', - description: '/docs/references/account/get-mfa-recovery-codes.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_MFA_RECOVERY_CODES, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'getMfaRecoveryCodes', + description: '/docs/references/account/get-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -4643,40 +4269,20 @@ App::delete('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'deleteMfaAuthenticator', - description: '/docs/references/account/delete-mfa-authenticator.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.deleteMFAAuthenticator', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'deleteMFAAuthenticator', - description: '/docs/references/account/delete-mfa-authenticator.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, - ) - ], - contentType: ContentType::NONE - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'deleteMfaAuthenticator', + description: '/docs/references/account/delete-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->inject('response') ->inject('user') @@ -4709,40 +4315,20 @@ App::post('/v1/account/mfa/challenge') ->label('audits.event', 'challenge.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'createMfaChallenge', - description: '/docs/references/account/create-mfa-challenge.md', - auth: [], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_MFA_CHALLENGE, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.createMFAChallenge', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'createMFAChallenge', - description: '/docs/references/account/create-mfa-challenge.md', - auth: [], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_CREATED, - model: Response::MODEL_MFA_CHALLENGE, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'createMfaChallenge', + description: '/docs/references/account/create-mfa-challenge.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_CHALLENGE, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') ->param('factor', '', new WhiteList([Type::EMAIL, Type::PHONE, Type::TOTP, Type::RECOVERY_CODE]), 'Factor used for verification. Must be one of following: `' . Type::EMAIL . '`, `' . Type::PHONE . '`, `' . Type::TOTP . '`, `' . Type::RECOVERY_CODE . '`.') @@ -4758,18 +4344,15 @@ App::post('/v1/account/mfa/challenge') ->inject('timelimit') ->inject('queueForStatsUsage') ->inject('plan') - ->inject('proofForToken') - ->inject('proofForCode') - ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan, ProofsToken $proofForToken, ProofsCode $proofForCode) { + ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { - $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), TOKEN_EXPIRATION_CONFIRM)); - - $code = $proofForCode->generate(); + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM)); + $code = Auth::codeGenerator(); $challenge = new Document([ 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), 'type' => $factor, - 'token' => $proofForToken->generate(), + 'token' => Auth::tokenGenerator(), 'code' => $code, 'expire' => $expire, '$permissions' => [ @@ -4854,18 +4437,7 @@ App::post('/v1/account/mfa/challenge') } $subject = $locale->getText("emails.mfaChallenge.subject"); - $preview = $locale->getText("emails.mfaChallenge.preview"); - $heading = $locale->getText("emails.mfaChallenge.heading"); - $customTemplate = $project->getAttribute('templates', [])['email.mfaChallenge-' . $locale->default] ?? []; - $smtpBaseTemplate = $project->getAttribute('smtpBaseTemplate', 'email-base'); - - $validator = new FileName(); - if (!$validator->isValid($smtpBaseTemplate)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid template path'); - } - - $bodyTemplate = __DIR__ . '/../../config/locale/templates/' . $smtpBaseTemplate . '.tpl'; $detector = new Detector($request->getUserAgent('UNKNOWN')); $agentOs = $detector->getOS(); @@ -4929,7 +4501,6 @@ App::post('/v1/account/mfa/challenge') } $emailVariables = [ - 'heading' => $heading, 'direction' => $locale->getText('settings.direction'), // {{user}}, {{project}} and {{otp}} are required in the templates 'user' => $user->getAttribute('name'), @@ -4937,26 +4508,12 @@ App::post('/v1/account/mfa/challenge') 'otp' => $code, 'agentDevice' => $agentDevice['deviceBrand'] ?? $agentDevice['deviceBrand'] ?? 'UNKNOWN', 'agentClient' => $agentClient['clientName'] ?? 'UNKNOWN', - 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN', + 'agentOs' => $agentOs['osName'] ?? 'UNKNOWN' ]; - if ($smtpBaseTemplate === APP_BRANDED_EMAIL_BASE_TEMPLATE) { - $emailVariables = array_merge($emailVariables, [ - 'accentColor' => APP_EMAIL_ACCENT_COLOR, - 'logoUrl' => APP_EMAIL_LOGO_URL, - 'twitterUrl' => APP_SOCIAL_TWITTER, - 'discordUrl' => APP_SOCIAL_DISCORD, - 'githubUrl' => APP_SOCIAL_GITHUB_APPWRITE, - 'termsUrl' => APP_EMAIL_TERMS_URL, - 'privacyUrl' => APP_EMAIL_PRIVACY_URL, - ]); - } - $queueForMails ->setSubject($subject) - ->setPreview($preview) ->setBody($body) - ->setBodyTemplate($bodyTemplate) ->setVariables($emailVariables) ->setRecipient($user->getAttribute('email')) ->trigger(); @@ -4978,40 +4535,20 @@ App::put('/v1/account/mfa/challenge') ->label('audits.event', 'challenges.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk', [ - new Method( - namespace: 'account', - group: 'mfa', - name: 'updateMfaChallenge', - description: '/docs/references/account/update-mfa-challenge.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_SESSION, - ) - ], - contentType: ContentType::JSON, - deprecated: new Deprecated( - since: '1.8.0', - replaceWith: 'account.updateMFAChallenge', - ), - ), - new Method( - namespace: 'account', - group: 'mfa', - name: 'updateMFAChallenge', - description: '/docs/references/account/update-mfa-challenge.md', - auth: [AuthType::SESSION, AuthType::JWT], - responses: [ - new SDKResponse( - code: Response::STATUS_CODE_OK, - model: Response::MODEL_SESSION, - ) - ], - contentType: ContentType::JSON - ) - ]) + ->label('sdk', new Method( + namespace: 'account', + group: 'mfa', + name: 'updateMfaChallenge', + description: '/docs/references/account/update-mfa-challenge.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},challengeId:{param-challengeId}') ->param('challengeId', '', new Text(256), 'ID of the challenge.') @@ -5079,8 +4616,8 @@ App::put('/v1/account/mfa/challenge') $dbForProject->updateDocument('sessions', $session->getId(), $session); $queueForEvents - ->setParam('userId', $user->getId()) - ->setParam('sessionId', $session->getId()); + ->setParam('userId', $user->getId()) + ->setParam('sessionId', $session->getId()); $response->dynamic($session, Response::MODEL_SESSION); }); @@ -5114,9 +4651,7 @@ App::post('/v1/account/targets/push') ->inject('request') ->inject('response') ->inject('dbForProject') - ->inject('store') - ->inject('proofForToken') - ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject, Store $store, ProofsToken $proofForToken) { + ->action(function (string $targetId, string $identifier, string $providerId, Event $queueForEvents, Document $user, Request $request, Response $response, Database $dbForProject) { $targetId = $targetId == 'unique()' ? ID::unique() : $targetId; $provider = Authorization::skip(fn () => $dbForProject->getDocument('providers', $providerId)); @@ -5132,7 +4667,7 @@ App::post('/v1/account/targets/push') $device = $detector->getDevice(); - $sessionId = Auth::sessionVerify($user->getAttribute('sessions', []), $store->getProperty('secret', ''), $proofForToken); + $sessionId = Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret); $session = $dbForProject->getDocument('sessions', $sessionId); try { @@ -5145,7 +4680,7 @@ App::post('/v1/account/targets/push') ], 'providerId' => !empty($providerId) ? $providerId : null, 'providerInternalId' => !empty($providerId) ? $provider->getSequence() : null, - 'providerType' => MESSAGE_TYPE_PUSH, + 'providerType' => MESSAGE_TYPE_PUSH, 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), 'sessionId' => $session->getId(), @@ -5306,11 +4841,10 @@ App::get('/v1/account/identities') contentType: ContentType::JSON )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('dbForProject') - ->action(function (array $queries, bool $includeTotal, Response $response, Document $user, Database $dbForProject) { + ->action(function (array $queries, Response $response, Document $user, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -5321,8 +4855,8 @@ App::get('/v1/account/identities') $queries[] = Query::equal('userInternalId', [$user->getSequence()]); /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -5351,7 +4885,7 @@ App::get('/v1/account/identities') } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT); $response->dynamic(new Document([ 'identities' => $results, From 232f1b1c0571571c519623580e9b82f2a9266dd9 Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 21 Oct 2025 11:24:09 +0300 Subject: [PATCH 13/20] account sync --- .../Account/AccountCustomClientTest.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index ae21ae75a8..0993f68a58 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -236,25 +236,6 @@ class AccountCustomClientTest extends Scope $this->assertEquals($sessionId, $response['body']['sessions'][0]['$id']); $this->assertEmpty($response['body']['sessions'][0]['secret']); - /** - * Test for SUCCESS with includeTotal=false - */ - $sessionsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/account/sessions', array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, - ]), [ - 'includeTotal' => false - ]); - - $this->assertEquals(200, $sessionsWithIncludeTotalFalse['headers']['status-code']); - $this->assertIsArray($sessionsWithIncludeTotalFalse['body']); - $this->assertIsArray($sessionsWithIncludeTotalFalse['body']['sessions']); - $this->assertIsInt($sessionsWithIncludeTotalFalse['body']['total']); - $this->assertEquals(0, $sessionsWithIncludeTotalFalse['body']['total']); - $this->assertGreaterThan(0, count($sessionsWithIncludeTotalFalse['body']['sessions'])); - $this->assertEquals('Windows', $response['body']['sessions'][0]['osName']); $this->assertEquals('WIN', $response['body']['sessions'][0]['osCode']); $this->assertEquals('10', $response['body']['sessions'][0]['osVersion']); From ab1e51034826dde50034e6e73fc5d546e800dd6d Mon Sep 17 00:00:00 2001 From: shimon Date: Tue, 21 Oct 2025 11:41:41 +0300 Subject: [PATCH 14/20] Enhance API response handling by adding 'includeTotal' parameter to account endpoints, allowing control over total count calculation for sessions, logs, and identities. Updated tests to verify functionality. --- app/controllers/api/account.php | 10 ++++++---- .../Account/AccountCustomClientTest.php | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 5563fc6a59..b9cbd0a217 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2814,12 +2814,13 @@ App::get('/v1/account/logs') contentType: ContentType::JSON, )) ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') ->inject('geodb') ->inject('dbForProject') - ->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { + ->action(function (array $queries, bool $includeTotal, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -2864,7 +2865,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getSequence(), $queries), + 'total' => $includeTotal ? $audit->countLogsByUser($user->getSequence(), $queries) : 0, 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -5211,10 +5212,11 @@ App::get('/v1/account/identities') contentType: ContentType::JSON )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) + ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('dbForProject') - ->action(function (array $queries, Response $response, Document $user, Database $dbForProject) { + ->action(function (array $queries, bool $includeTotal, Response $response, Document $user, Database $dbForProject) { try { $queries = Query::parseQueries($queries); @@ -5259,7 +5261,7 @@ App::get('/v1/account/identities') $response->dynamic(new Document([ 'identities' => $results, - 'total' => $total, + 'total' => $includeTotal ? $total : 0, ]), Response::MODEL_IDENTITY_LIST); }); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 0993f68a58..faa508d020 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -389,6 +389,26 @@ class AccountCustomClientTest extends Scope $this->assertIsNumeric($responseLimitOffset['body']['total']); $this->assertEquals($response['body']['logs'][1], $responseLimitOffset['body']['logs'][0]); + + /** + * Test for includeTotal=false + */ + $logsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]), [ + 'includeTotal' => false + ]); + + $this->assertEquals(200, $logsWithIncludeTotalFalse['headers']['status-code']); + $this->assertIsArray($logsWithIncludeTotalFalse['body']); + $this->assertIsArray($logsWithIncludeTotalFalse['body']['logs']); + $this->assertIsInt($logsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $logsWithIncludeTotalFalse['body']['total']); + $this->assertGreaterThan(0, count($logsWithIncludeTotalFalse['body']['logs'])); + /** * Test for FAILURE */ From f18aa6b6486d52ef97674c1ac483c476b85a6f21 Mon Sep 17 00:00:00 2001 From: shimon Date: Mon, 27 Oct 2025 10:14:41 +0200 Subject: [PATCH 15/20] composer.lock --- composer.lock | 204 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 149 insertions(+), 55 deletions(-) diff --git a/composer.lock b/composer.lock index 08ef7ef8ed..f73c0352d9 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": "407c1717bfef580d733ff2bbb232ec8a", + "content-hash": "f826d3b283b10af98dfd565c4187a83a", "packages": [ { "name": "adhocore/jwt", @@ -3790,6 +3790,54 @@ }, "time": "2020-10-24T09:49:09+00:00" }, + { + "name": "utopia-php/console", + "version": "0.0.1", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/console.git", + "reference": "f77104e4a888fa9cb3e08f32955ec09479ab7a92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/console/zipball/f77104e4a888fa9cb3e08f32955ec09479ab7a92", + "reference": "f77104e4a888fa9cb3e08f32955ec09479ab7a92", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.6", + "swoole/ide-helper": "4.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Console helpers for logging, prompting, and executing commands", + "keywords": [ + "cli", + "console", + "php", + "terminal", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/console/issues", + "source": "https://github.com/utopia-php/console/tree/0.0.1" + }, + "time": "2025-10-20T14:41:36+00:00" + }, { "name": "utopia-php/database", "version": "3.0.2", @@ -3850,16 +3898,16 @@ }, { "name": "utopia-php/detector", - "version": "0.1.5", + "version": "0.2.0", "source": { "type": "git", "url": "https://github.com/utopia-php/detector.git", - "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718" + "reference": "795ed56169af833fd6a4ea58a6c747e05ccc7ba6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/detector/zipball/b5d6ba51352485b524589bc0ee8d07a9efafe718", - "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/795ed56169af833fd6a4ea58a6c747e05ccc7ba6", + "reference": "795ed56169af833fd6a4ea58a6c747e05ccc7ba6", "shasum": "" }, "require": { @@ -3889,9 +3937,9 @@ ], "support": { "issues": "https://github.com/utopia-php/detector/issues", - "source": "https://github.com/utopia-php/detector/tree/0.1.5" + "source": "https://github.com/utopia-php/detector/tree/0.2.0" }, - "time": "2025-05-19T11:01:28+00:00" + "time": "2025-10-21T13:57:30+00:00" }, { "name": "utopia-php/dns", @@ -3951,21 +3999,22 @@ }, { "name": "utopia-php/domains", - "version": "0.8.4", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/utopia-php/domains.git", - "reference": "316a76b0fcbc7f82e40be466c22c19acb243ee22" + "reference": "99b4ec95d5d6b7a5c990a66c56412212d9af37e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/domains/zipball/316a76b0fcbc7f82e40be466c22c19acb243ee22", - "reference": "316a76b0fcbc7f82e40be466c22c19acb243ee22", + "url": "https://api.github.com/repos/utopia-php/domains/zipball/99b4ec95d5d6b7a5c990a66c56412212d9af37e7", + "reference": "99b4ec95d5d6b7a5c990a66c56412212d9af37e7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/framework": "0.33.*" + "utopia-php/cache": "0.13.*", + "utopia-php/validators": "0.0.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -4006,9 +4055,9 @@ ], "support": { "issues": "https://github.com/utopia-php/domains/issues", - "source": "https://github.com/utopia-php/domains/tree/0.8.4" + "source": "https://github.com/utopia-php/domains/tree/0.9.1" }, - "time": "2025-10-17T11:31:56+00:00" + "time": "2025-10-21T14:52:27+00:00" }, { "name": "utopia-php/dsn", @@ -4295,16 +4344,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.19.0", + "version": "0.20.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8" + "reference": "6c5be4588d97e3732a1907ecb13cd8a098eade96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8", - "reference": "0b866d54e70c792a3c4f5ca9c12a6d358a31f4b8", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/6c5be4588d97e3732a1907ecb13cd8a098eade96", + "reference": "6c5be4588d97e3732a1907ecb13cd8a098eade96", "shasum": "" }, "require": { @@ -4340,22 +4389,22 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.19.0" + "source": "https://github.com/utopia-php/messaging/tree/0.20.0" }, - "time": "2025-10-14T11:46:49+00:00" + "time": "2025-10-22T04:27:37+00:00" }, { "name": "utopia-php/migration", - "version": "1.2.2", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "e0b6687620dd67fe2b96eb4419e8243577b11c8f" + "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/e0b6687620dd67fe2b96eb4419e8243577b11c8f", - "reference": "e0b6687620dd67fe2b96eb4419e8243577b11c8f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/f5c1d2cae764290766a4c2d1546c1d51de95b67f", + "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f", "shasum": "" }, "require": { @@ -4363,9 +4412,9 @@ "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", + "utopia-php/console": "0.0.*", "utopia-php/database": "3.*", "utopia-php/dsn": "0.2.*", - "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" }, "require-dev": { @@ -4373,7 +4422,6 @@ "laravel/pint": "1.*", "phpstan/phpstan": "1.*", "phpunit/phpunit": "11.*", - "utopia-php/cli": "0.16.*", "vlucas/phpdotenv": "5.*" }, "type": "library", @@ -4396,9 +4444,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.2.2" + "source": "https://github.com/utopia-php/migration/tree/1.3.2" }, - "time": "2025-10-20T10:12:11+00:00" + "time": "2025-10-22T12:30:47+00:00" }, { "name": "utopia-php/mongo", @@ -5000,17 +5048,63 @@ "time": "2025-03-17T11:57:52+00:00" }, { - "name": "utopia-php/vcs", - "version": "0.11.0", + "name": "utopia-php/validators", + "version": "0.0.2", "source": { "type": "git", - "url": "https://github.com/utopia-php/vcs.git", - "reference": "0e665eaa7d906168525bf6aac50b6bcc3e4fe528" + "url": "https://github.com/utopia-php/validators.git", + "reference": "894210695c5d35fa248fb65f7fe7237b6ff4fb0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/0e665eaa7d906168525bf6aac50b6bcc3e4fe528", - "reference": "0e665eaa7d906168525bf6aac50b6bcc3e4fe528", + "url": "https://api.github.com/repos/utopia-php/validators/zipball/894210695c5d35fa248fb65f7fe7237b6ff4fb0b", + "reference": "894210695c5d35fa248fb65f7fe7237b6ff4fb0b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-xdebug": "*", + "laravel/pint": "^1.2", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "^9.5.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A lightweight collection of reusable validators for Utopia projects", + "keywords": [ + "php", + "utopia", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/utopia-php/validators/issues", + "source": "https://github.com/utopia-php/validators/tree/0.0.2" + }, + "time": "2025-10-20T21:52:28+00:00" + }, + { + "name": "utopia-php/vcs", + "version": "0.12.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/vcs.git", + "reference": "28457cf347972c4ec95d3ca77776a4921364a665" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/28457cf347972c4ec95d3ca77776a4921364a665", + "reference": "28457cf347972c4ec95d3ca77776a4921364a665", "shasum": "" }, "require": { @@ -5044,9 +5138,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.11.0" + "source": "https://github.com/utopia-php/vcs/tree/0.12.0" }, - "time": "2025-07-23T13:54:58+00:00" + "time": "2025-10-22T12:58:29+00:00" }, { "name": "utopia-php/websocket", @@ -5224,16 +5318,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.5", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "0c4f514bf861f42555dae781f394fefeb27ff521" + "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0c4f514bf861f42555dae781f394fefeb27ff521", - "reference": "0c4f514bf861f42555dae781f394fefeb27ff521", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/efda55836d19b8d5f36ac0df33c83b48af0aa8fd", + "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd", "shasum": "" }, "require": { @@ -5269,9 +5363,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.5" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.12" }, - "time": "2025-10-21T04:59:59+00:00" + "time": "2025-10-25T05:39:48+00:00" }, { "name": "doctrine/annotations", @@ -5748,16 +5842,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.6.1", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + "reference": "3a454ca033b9e06b63282ce19562e892747449bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", + "reference": "3a454ca033b9e06b63282ce19562e892747449bb", "shasum": "" }, "require": { @@ -5800,9 +5894,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" }, - "time": "2025-08-13T20:13:15+00:00" + "time": "2025-10-21T19:32:17+00:00" }, { "name": "phar-io/manifest", @@ -5975,16 +6069,16 @@ }, { "name": "phpbench/phpbench", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b" + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", - "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018", + "reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018", "shasum": "" }, "require": { @@ -6011,7 +6105,7 @@ "ergebnis/composer-normalize": "^2.39", "friendsofphp/php-cs-fixer": "^3.0", "jangregor/phpstan-prophecy": "^1.0", - "phpspec/prophecy": "dev-master", + "phpspec/prophecy": "^1.22", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", @@ -6061,7 +6155,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.4.1" + "source": "https://github.com/phpbench/phpbench/tree/1.4.2" }, "funding": [ { @@ -6069,7 +6163,7 @@ "type": "github" } ], - "time": "2025-03-12T08:01:40+00:00" + "time": "2025-10-26T14:21:59+00:00" }, { "name": "phpstan/phpstan", From 33000134df824e0e1277d94260e2aa0b11e45860 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 29 Oct 2025 09:17:10 +0200 Subject: [PATCH 16/20] addrising comments + composer.lock --- app/controllers/api/account.php | 4 +- app/controllers/api/users.php | 3 +- composer.lock | 134 +++++++++++++++++++++++--------- 3 files changed, 100 insertions(+), 41 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index b9cbd0a217..7c6ad629f9 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -5257,11 +5257,11 @@ App::get('/v1/account/identities') } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } - $total = $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT); + $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; $response->dynamic(new Document([ 'identities' => $results, - 'total' => $includeTotal ? $total : 0, + 'total' => $total, ]), Response::MODEL_IDENTITY_LIST); }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 0a0990ad39..5b66ff824c 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -1105,10 +1105,9 @@ App::get('/v1/users/identities') $cursor->setValue($cursorDocument); } - $filterQueries = Query::groupByType($queries)['filters']; try { $identities = $dbForProject->find('identities', $queries); - $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('identities', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } diff --git a/composer.lock b/composer.lock index f73c0352d9..9bb2f6a074 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": "f826d3b283b10af98dfd565c4187a83a", + "content-hash": "66e5a72649d7f816ba8ec979faca4cd8", "packages": [ { "name": "adhocore/jwt", @@ -3840,16 +3840,16 @@ }, { "name": "utopia-php/database", - "version": "3.0.2", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e" + "reference": "a83997d5555d6cd873b829a2459292211c6ab13f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e", - "reference": "b92554e2e7b3b00f0f0acb2b53c6a11e1349b81e", + "url": "https://api.github.com/repos/utopia-php/database/zipball/a83997d5555d6cd873b829a2459292211c6ab13f", + "reference": "a83997d5555d6cd873b829a2459292211c6ab13f", "shasum": "" }, "require": { @@ -3892,22 +3892,22 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/3.0.2" + "source": "https://github.com/utopia-php/database/tree/3.0.4" }, - "time": "2025-10-20T23:58:56+00:00" + "time": "2025-10-28T08:21:21+00:00" }, { "name": "utopia-php/detector", - "version": "0.2.0", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/utopia-php/detector.git", - "reference": "795ed56169af833fd6a4ea58a6c747e05ccc7ba6" + "reference": "89f96e864220de13800cf398a1f1686a85401eaa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/detector/zipball/795ed56169af833fd6a4ea58a6c747e05ccc7ba6", - "reference": "795ed56169af833fd6a4ea58a6c747e05ccc7ba6", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/89f96e864220de13800cf398a1f1686a85401eaa", + "reference": "89f96e864220de13800cf398a1f1686a85401eaa", "shasum": "" }, "require": { @@ -3937,9 +3937,9 @@ ], "support": { "issues": "https://github.com/utopia-php/detector/issues", - "source": "https://github.com/utopia-php/detector/tree/0.2.0" + "source": "https://github.com/utopia-php/detector/tree/0.2.1" }, - "time": "2025-10-21T13:57:30+00:00" + "time": "2025-10-27T13:38:33+00:00" }, { "name": "utopia-php/dns", @@ -4106,6 +4106,66 @@ }, "time": "2024-05-07T02:01:25+00:00" }, + { + "name": "utopia-php/emails", + "version": "0.6.2", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/emails.git", + "reference": "9c4c40cf7c03c2e9e21364566f9b192d03ea93c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/emails/zipball/9c4c40cf7c03c2e9e21364566f9b192d03ea93c9", + "reference": "9c4c40cf7c03c2e9e21364566f9b192d03ea93c9", + "shasum": "" + }, + "require": { + "php": ">=8.0", + "utopia-php/cli": "^0.15", + "utopia-php/domains": "^0.9", + "utopia-php/fetch": "^0.4", + "utopia-php/validators": "^0.0.2" + }, + "require-dev": { + "laravel/pint": "1.25.*", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Emails\\": "src/Emails" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eldad Fux", + "email": "eldad@appwrite.io" + } + ], + "description": "Utopia Emails library is simple and lite library for parsing and validating email addresses. This library is aiming to be as simple and easy to learn and use.", + "keywords": [ + "RFC5322", + "email", + "emails", + "framework", + "parsing", + "php", + "upf", + "utopia", + "validation" + ], + "support": { + "issues": "https://github.com/utopia-php/emails/issues", + "source": "https://github.com/utopia-php/emails/tree/0.6.2" + }, + "time": "2025-10-28T16:08:17+00:00" + }, { "name": "utopia-php/fetch", "version": "0.4.2", @@ -4395,16 +4455,16 @@ }, { "name": "utopia-php/migration", - "version": "1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f" + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/f5c1d2cae764290766a4c2d1546c1d51de95b67f", - "reference": "f5c1d2cae764290766a4c2d1546c1d51de95b67f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/731b3a963c58c30e0b2368695d57a7e8fcb7455c", + "reference": "731b3a963c58c30e0b2368695d57a7e8fcb7455c", "shasum": "" }, "require": { @@ -4444,9 +4504,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/1.3.2" + "source": "https://github.com/utopia-php/migration/tree/1.3.3" }, - "time": "2025-10-22T12:30:47+00:00" + "time": "2025-10-28T04:02:08+00:00" }, { "name": "utopia-php/mongo", @@ -5318,16 +5378,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "1.4.12", + "version": "1.4.15", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd" + "reference": "b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/efda55836d19b8d5f36ac0df33c83b48af0aa8fd", - "reference": "efda55836d19b8d5f36ac0df33c83b48af0aa8fd", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda", + "reference": "b4a2fd9e92903c2e156f17fc5dafe102e6cfdfda", "shasum": "" }, "require": { @@ -5363,9 +5423,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/1.4.12" + "source": "https://github.com/appwrite/sdk-generator/tree/1.4.15" }, - "time": "2025-10-25T05:39:48+00:00" + "time": "2025-10-28T04:52:59+00:00" }, { "name": "doctrine/annotations", @@ -7812,16 +7872,16 @@ }, { "name": "symfony/console", - "version": "v7.3.4", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db" + "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", - "reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", + "url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7", + "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7", "shasum": "" }, "require": { @@ -7886,7 +7946,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.4" + "source": "https://github.com/symfony/console/tree/v7.3.5" }, "funding": [ { @@ -7906,7 +7966,7 @@ "type": "tidelift" } ], - "time": "2025-09-22T15:31:00+00:00" + "time": "2025-10-14T15:46:26+00:00" }, { "name": "symfony/filesystem", @@ -7980,16 +8040,16 @@ }, { "name": "symfony/finder", - "version": "v7.3.2", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + "reference": "9f696d2f1e340484b4683f7853b273abff94421f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", - "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", + "reference": "9f696d2f1e340484b4683f7853b273abff94421f", "shasum": "" }, "require": { @@ -8024,7 +8084,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.2" + "source": "https://github.com/symfony/finder/tree/v7.3.5" }, "funding": [ { @@ -8044,7 +8104,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2025-10-15T18:45:57+00:00" }, { "name": "symfony/options-resolver", From a7dbb3daeaba54e0eefb43970bb2418631570ec2 Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 29 Oct 2025 11:08:08 +0200 Subject: [PATCH 17/20] Refactor API parameters to replace 'includeTotal' with 'total' across multiple endpoints for consistency in response handling. --- app/controllers/api/account.php | 4 ++-- app/controllers/api/messaging.php | 18 +++++++++--------- app/controllers/api/migrations.php | 2 +- app/controllers/api/projects.php | 6 +++--- app/controllers/api/storage.php | 4 ++-- app/controllers/api/teams.php | 6 +++--- app/controllers/api/users.php | 12 ++++++------ app/controllers/api/vcs.php | 2 +- .../Databases/Collections/Attributes/XList.php | 2 +- .../Databases/Collections/Documents/XList.php | 2 +- .../Databases/Collections/Indexes/XList.php | 2 +- .../Http/Databases/Collections/XList.php | 2 +- .../Modules/Databases/Http/Databases/XList.php | 2 +- .../Http/TablesDB/Tables/Columns/XList.php | 2 +- .../Http/TablesDB/Tables/Indexes/XList.php | 2 +- .../Http/TablesDB/Tables/Rows/XList.php | 2 +- .../Databases/Http/TablesDB/Tables/XList.php | 2 +- .../Modules/Databases/Http/TablesDB/XList.php | 2 +- .../Functions/Http/Deployments/XList.php | 2 +- .../Functions/Http/Executions/XList.php | 2 +- .../Modules/Functions/Http/Functions/XList.php | 2 +- .../Modules/Functions/Http/Templates/XList.php | 2 +- .../Modules/Projects/Http/Projects/XList.php | 2 +- .../Modules/Proxy/Http/Rules/XList.php | 2 +- .../Modules/Sites/Http/Deployments/XList.php | 2 +- .../Platform/Modules/Sites/Http/Logs/XList.php | 2 +- .../Modules/Sites/Http/Sites/XList.php | 2 +- .../Tokens/Http/Tokens/Buckets/Files/XList.php | 2 +- .../Account/AccountCustomClientTest.php | 4 ++-- .../Databases/Legacy/DatabasesBase.php | 4 ++-- .../Legacy/DatabasesCustomServerTest.php | 12 ++++++------ .../TablesDB/DatabasesCustomServerTest.php | 4 ++-- .../Functions/FunctionsCustomClientTest.php | 4 ++-- .../Functions/FunctionsCustomServerTest.php | 8 ++++---- tests/e2e/Services/Messaging/MessagingBase.php | 4 ++-- tests/e2e/Services/Storage/StorageBase.php | 4 ++-- tests/e2e/Services/Teams/TeamsBase.php | 4 ++-- tests/e2e/Services/Users/UsersBase.php | 4 ++-- 38 files changed, 73 insertions(+), 73 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 7c6ad629f9..47557e856e 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -2814,7 +2814,7 @@ App::get('/v1/account/logs') contentType: ContentType::JSON, )) ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('locale') @@ -5212,7 +5212,7 @@ App::get('/v1/account/identities') contentType: ContentType::JSON )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('user') ->inject('dbForProject') diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 3f4d75512f..5193d0b30f 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -1067,7 +1067,7 @@ App::get('/v1/messaging/providers') )) ->param('queries', [], new Providers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -1136,7 +1136,7 @@ App::get('/v1/messaging/providers/:providerId/logs') )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -2474,7 +2474,7 @@ App::get('/v1/messaging/topics') )) ->param('queries', [], new Topics(), '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(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -2543,7 +2543,7 @@ App::get('/v1/messaging/topics/:topicId/logs') )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -2877,7 +2877,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('queries', [], new Subscribers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -2966,7 +2966,7 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') )) ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -3697,7 +3697,7 @@ App::get('/v1/messaging/messages') )) ->param('queries', [], new Messages(), '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(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('dbForProject') ->inject('response') ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { @@ -3766,7 +3766,7 @@ App::get('/v1/messaging/messages/:messageId/logs') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -3865,7 +3865,7 @@ App::get('/v1/messaging/messages/:messageId/targets') )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $messageId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 76e0c71304..1d1e6e999c 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -597,7 +597,7 @@ App::get('/v1/migrations') )) ->param('queries', [], new Migrations(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Migrations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 4abe4e0723..2b30b1cd08 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1234,7 +1234,7 @@ App::get('/v1/projects/:projectId/webhooks') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { @@ -1532,7 +1532,7 @@ App::get('/v1/projects/:projectId/keys') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { @@ -1836,7 +1836,7 @@ App::get('/v1/projects/:projectId/platforms') ] )) ->param('projectId', '', new UID(), 'Project unique ID.') - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->action(function (string $projectId, bool $includeTotal, Response $response, Database $dbForPlatform) { diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 70adbfa717..72acd7b4a2 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -180,7 +180,7 @@ App::get('/v1/storage/buckets') )) ->param('queries', [], new Buckets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -786,7 +786,7 @@ App::get('/v1/storage/buckets/:bucketId/files') ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('queries', [], new Files(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('mode') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index fdf363d793..9fb5db0c5b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -170,7 +170,7 @@ App::get('/v1/teams') )) ->param('queries', [], new Teams(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -840,7 +840,7 @@ App::get('/v1/teams/:teamId/memberships') ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') @@ -1433,7 +1433,7 @@ App::get('/v1/teams/:teamId/logs') )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 5b66ff824c..591a22705d 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -605,7 +605,7 @@ App::get('/v1/users') )) ->param('queries', [], new Users(), '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(', ', Users::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -785,7 +785,7 @@ App::get('/v1/users/:userId/sessions') ] )) ->param('userId', '', new UID(), 'User ID.') - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -835,7 +835,7 @@ App::get('/v1/users/:userId/memberships') ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $userId, array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { @@ -895,7 +895,7 @@ App::get('/v1/users/:userId/logs') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('locale') @@ -993,7 +993,7 @@ App::get('/v1/users/:userId/targets') )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Targets(), '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(', ', Targets::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (string $userId, array $queries, bool $includeTotal, Response $response, Database $dbForProject) { @@ -1065,7 +1065,7 @@ App::get('/v1/users/identities') )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, bool $includeTotal, Response $response, Database $dbForProject) { diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 2f5e2de48f..a6e72bf476 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -1535,7 +1535,7 @@ App::get('/v1/vcs/installations') )) ->param('queries', [], new Installations(), '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(', ', Installations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php index a611e04de9..c2af3ac945 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php @@ -61,7 +61,7 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->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) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 04d0f85fb6..f159043531 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -68,7 +68,7 @@ class XList extends Action ->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 ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php index 223fa7dd87..88b3a32e0b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php @@ -63,7 +63,7 @@ class XList extends Action ->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) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php index 2ce88c3b25..286e48420a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php @@ -64,7 +64,7 @@ class XList extends Action ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Collections(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php index 5a792093e8..b1d2ff9346 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php @@ -59,7 +59,7 @@ class XList extends Action ]) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php index 8eebf0260f..1e0b641b32 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php @@ -49,7 +49,7 @@ class XList extends AttributesXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID.') ->param('queries', [], new Columns(), '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 columns: ' . implode(', ', Columns::ALLOWED_COLUMNS), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php index 1bac24a1dd..0ea52eaf1b 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php @@ -51,7 +51,7 @@ class XList extends IndexXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the Database service [server integration](https://appwrite.io/docs/references/cloud/server-dart/tablesDB#createTable).') ->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 columns: ' . implode(', ', Indexes::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php index 9ce815d2ab..b96e84b722 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php @@ -53,7 +53,7 @@ class XList extends DocumentXList ->param('tableId', '', new UID(), 'Table ID. You can create a new table using the TablesDB service [server integration](https://appwrite.io/docs/products/databases/tables#create-table).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long.', true) ->param('transactionId', null, new UID(), 'Transaction ID to read uncommitted changes within the transaction.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php index efe066773b..5e8fcfc3c8 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php @@ -52,7 +52,7 @@ class XList extends CollectionXList ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Tables(), '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 columns: ' . implode(', ', Tables::ALLOWED_COLUMNS), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php index 1653f1ca50..2f07c4843a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php @@ -45,7 +45,7 @@ class XList extends DatabaseXList )) ->param('queries', [], new Databases(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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 columns: ' . implode(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 243c2ee5f3..79e0d382ed 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 3442280a0c..3d5ec06ace 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -57,7 +57,7 @@ class XList extends Base )) ->param('functionId', '', new UID(), 'Function ID.') ->param('queries', [], new Executions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php index a5af6fb89c..ef41562947 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -55,7 +55,7 @@ class XList extends Base )) ->param('queries', [], new Functions(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Functions::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php index b29f42a7bc..26b85c8065 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php @@ -53,7 +53,7 @@ class XList extends Base ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->callback($this->action(...)); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php index ddd38a3851..692b467282 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php @@ -60,7 +60,7 @@ class XList extends Action )) ->param('queries', [], $this->getQueriesValidator(), '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(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForPlatform') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php index bba279fea1..86f63bc258 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php @@ -52,7 +52,7 @@ class XList extends Action )) ->param('queries', [], new Rules(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Rules::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('project') ->inject('dbForPlatform') diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index 729bb2798b..7182e4213e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -58,7 +58,7 @@ class XList extends Base ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Deployments(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/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(', ', Deployments::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('request') ->inject('response') ->inject('dbForProject') diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index 0de403a03f..10c7245761 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -56,7 +56,7 @@ class XList extends Base )) ->param('siteId', '', new UID(), 'Site ID.') ->param('queries', [], new Logs(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php index be3f1cc60a..4ba45a3d9f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -55,7 +55,7 @@ class XList extends Base )) ->param('queries', [], new Sites(), '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(', ', Sites::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index ac78b482ec..8a9301713b 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -54,7 +54,7 @@ class XList extends Action ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') ->param('queries', [], new FileTokens(), '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(', ', FileTokens::ALLOWED_ATTRIBUTES), true) - ->param('includeTotal', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) + ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') ->inject('dbForProject') ->callback($this->action(...)); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index faa508d020..8127b8a1cd 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -391,7 +391,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['body']['logs'][1], $responseLimitOffset['body']['logs'][0]); /** - * Test for includeTotal=false + * Test for total=false */ $logsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/account/logs', array_merge([ 'origin' => 'http://localhost', @@ -399,7 +399,7 @@ class AccountCustomClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $logsWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php index ec1c7632ed..ae4e10196f 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesBase.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesBase.php @@ -962,14 +962,14 @@ trait DatabasesBase $this->assertEquals(12, $attributes['body']['total']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $attributesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $attributesWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php index f9fcf24c18..22ce1eb1e3 100644 --- a/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php @@ -56,13 +56,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test2['body']['$id'], $databases['body']['databases'][1]['$id']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $databasesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $databasesWithIncludeTotalFalse['headers']['status-code']); @@ -413,13 +413,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test1['body']['enabled'], $collections['body']['collections'][0]['enabled']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $collectionsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $collectionsWithIncludeTotalFalse['headers']['status-code']); @@ -4583,13 +4583,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(10, $documents['body']['total']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $documentsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $documentsWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php index 5db78ed9a1..7b84420640 100644 --- a/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php @@ -56,13 +56,13 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals($test2['body']['$id'], $databases['body']['databases'][1]['$id']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $databasesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/tablesdb', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $databasesWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 5e1fd8881e..cc978a8e38 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -377,13 +377,13 @@ class FunctionsCustomClientTest extends Scope $this->assertIsArray($templates['body']['templates']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $templatesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $templatesWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index b0a05bf591..f5846af959 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -419,9 +419,9 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(1, $deployments['body']['total']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ - $deploymentsWithIncludeTotalFalse = $this->listDeployments($functionId, ['includeTotal' => false]); + $deploymentsWithIncludeTotalFalse = $this->listDeployments($functionId, ['total' => false]); $this->assertEquals(200, $deploymentsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($deploymentsWithIncludeTotalFalse['body']); @@ -1017,9 +1017,9 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($data['deploymentId'], $executions['body']['executions'][0]['deploymentId']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ - $executionsWithIncludeTotalFalse = $this->listExecutions($data['functionId'], ['includeTotal' => false]); + $executionsWithIncludeTotalFalse = $this->listExecutions($data['functionId'], ['total' => false]); $this->assertEquals(200, $executionsWithIncludeTotalFalse['headers']['status-code']); $this->assertIsArray($executionsWithIncludeTotalFalse['body']); diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 583627c2d4..f5fdbc93ba 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -645,14 +645,14 @@ trait MessagingBase } /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $subscribersWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/messaging/topics/' . $data['topicId'] . '/subscribers', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $subscribersWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 361e561283..6879645a22 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -380,13 +380,13 @@ trait StorageBase $this->assertGreaterThan(0, count($files['body']['files'])); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $filesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $filesWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index ae85e80b91..0924b09af8 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -323,13 +323,13 @@ trait TeamsBase $this->assertEquals(400, $response['headers']['status-code']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $teamsWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $teamsWithIncludeTotalFalse['headers']['status-code']); diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index aaa00c98ff..37b9a7a605 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -799,13 +799,13 @@ trait UsersBase $this->assertGreaterThan(0, $users['body']['total']); /** - * Test for SUCCESS with includeTotal=false + * Test for SUCCESS with total=false */ $usersWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/users', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'includeTotal' => false + 'total' => false ]); $this->assertEquals(200, $usersWithIncludeTotalFalse['headers']['status-code']); From 2951a1b7b896ccbbf32ef3c5b4308527e11f6004 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 29 Oct 2025 15:11:42 +0530 Subject: [PATCH 18/20] fix: testListSites 2 not matching expected 1 --- tests/e2e/Services/Sites/SitesCustomServerTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index c8301b9428..a89d4e8099 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -641,7 +641,9 @@ class SitesCustomServerTest extends Scope 'siteId' => ID::unique() ]); - $sites = $this->listSites(); + $sites = $this->listSites([ + 'siteId' => $siteId, + ]); $this->assertEquals($sites['headers']['status-code'], 200); $this->assertCount(1, $sites['body']['sites']); From 1180dc0781ffd880045a998e52b1dd57a7a128fa Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 29 Oct 2025 15:13:33 +0530 Subject: [PATCH 19/20] use search --- tests/e2e/Services/Sites/SitesCustomServerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index a89d4e8099..6a5af920cc 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -634,7 +634,7 @@ class SitesCustomServerTest extends Scope 'buildRuntime' => 'node-22', 'fallbackFile' => '', 'framework' => 'other', - 'name' => 'Test Site', + 'name' => 'Test List Sites', 'outputDirectory' => './', 'providerBranch' => 'main', 'providerRootDirectory' => './', @@ -642,7 +642,7 @@ class SitesCustomServerTest extends Scope ]); $sites = $this->listSites([ - 'siteId' => $siteId, + 'search' => 'Test List Sites', ]); $this->assertEquals($sites['headers']['status-code'], 200); From d995dbb1590d7b56e54b2f1f57a99bb7b9f14b02 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Wed, 29 Oct 2025 15:19:16 +0530 Subject: [PATCH 20/20] fix: naming --- .../Services/Sites/SitesCustomServerTest.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 6a5af920cc..8591514796 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -647,7 +647,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals($sites['headers']['status-code'], 200); $this->assertCount(1, $sites['body']['sites']); - $this->assertEquals($sites['body']['sites'][0]['name'], 'Test Site'); + $this->assertEquals($sites['body']['sites'][0]['name'], 'Test List Sites'); // Test pagination limit $sites = $this->listSites([ @@ -691,7 +691,7 @@ class SitesCustomServerTest extends Scope // Test search name $sites = $this->listSites([ - 'search' => 'Test' + 'search' => 'Test List Sites' ]); $this->assertEquals($sites['headers']['status-code'], 200); @@ -714,21 +714,23 @@ class SitesCustomServerTest extends Scope 'buildRuntime' => 'node-22', 'fallbackFile' => '', 'framework' => 'other', - 'name' => 'Test Site 2', + 'name' => 'Test List Sites 2', 'outputDirectory' => './', 'providerBranch' => 'main', 'providerRootDirectory' => './', 'siteId' => ID::unique() ]); - $sites = $this->listSites(); + $sites = $this->listSites([ + 'search' => 'Test List Sites', + ]); $this->assertEquals($sites['headers']['status-code'], 200); $this->assertEquals($sites['body']['total'], 2); $this->assertIsArray($sites['body']['sites']); $this->assertCount(2, $sites['body']['sites']); - $this->assertEquals($sites['body']['sites'][0]['name'], 'Test Site'); - $this->assertEquals($sites['body']['sites'][1]['name'], 'Test Site 2'); + $this->assertEquals($sites['body']['sites'][0]['name'], 'Test List Sites'); + $this->assertEquals($sites['body']['sites'][1]['name'], 'Test List Sites 2'); $sites1 = $this->listSites([ 'queries' => [ @@ -738,7 +740,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals($sites1['headers']['status-code'], 200); $this->assertCount(1, $sites1['body']['sites']); - $this->assertEquals($sites1['body']['sites'][0]['name'], 'Test Site 2'); + $this->assertEquals($sites1['body']['sites'][0]['name'], 'Test List Sites 2'); $sites2 = $this->listSites([ 'queries' => [ @@ -748,7 +750,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals($sites2['headers']['status-code'], 200); $this->assertCount(1, $sites2['body']['sites']); - $this->assertEquals($sites2['body']['sites'][0]['name'], 'Test Site'); + $this->assertEquals($sites2['body']['sites'][0]['name'], 'Test List Sites'); /** * Test for FAILURE