diff --git a/app/config/collections2.php b/app/config/collections2.php index bc78efea75..052ba7cd00 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -546,13 +546,24 @@ $collections = [ 'array' => false, 'filters' => ['subQueryDomains'], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ - '$id' => '_fulltext_name', + '$id' => '_key_search', 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [1024], + 'attributes' => ['search'], + 'lengths' => [2048], 'orders' => [Database::ORDER_ASC], ], ], @@ -1049,6 +1060,17 @@ $collections = [ 'array' => true, 'filters' => ['json'], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => 'deleted', 'type' => Database::VAR_BOOLEAN, @@ -1069,6 +1091,13 @@ $collections = [ 'lengths' => [320], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => '_key_search', + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], [ '$id' => '_key_deleted_email', 'type' => Database::INDEX_KEY, @@ -1365,13 +1394,24 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ - '$id' => '_fulltext_name', + '$id' => '_key_search', 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [1024], + 'attributes' => ['search'], + 'lengths' => [2048], 'orders' => [Database::ORDER_ASC], ], ], @@ -1645,6 +1685,17 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ @@ -1655,10 +1706,10 @@ $collections = [ 'orders' => [Database::ORDER_ASC], ], [ - '$id' => '_fulltext_name', + '$id' => '_key_search', 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [1024], + 'attributes' => ['search'], + 'lengths' => [2048], 'orders' => [Database::ORDER_ASC], ], ], @@ -1813,13 +1864,24 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ - '$id' => '_fulltext_name', + '$id' => '_key_search', 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [1024], + 'attributes' => ['search'], + 'lengths' => [2048], 'orders' => [Database::ORDER_ASC], ], ], @@ -1886,6 +1948,17 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ @@ -1895,6 +1968,13 @@ $collections = [ 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => '_key_search', + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [2048], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -2003,6 +2083,17 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'search', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ @@ -2012,6 +2103,13 @@ $collections = [ 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => '_fulltext_search', + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [16384], + 'orders' => [Database::ORDER_ASC], + ], ], ], @@ -2187,4 +2285,4 @@ $collections = [ ] ]; -return $collections; +return $collections; \ No newline at end of file diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 3ad04efe81..7619301d18 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -107,6 +107,7 @@ App::post('/v1/account') 'sessions' => [], 'tokens' => [], 'memberships' => [], + 'search' => implode(' ', [$userId, $email, $name]), 'deleted' => false ])); } catch (Duplicate $th) { @@ -205,8 +206,8 @@ App::post('/v1/account/sessions') Authorization::setRole('user:' . $profile->getId()); $session = $dbForInternal->createDocument('sessions', $session - ->setAttribute('$read', ['user:' . $profile->getId()]) - ->setAttribute('$write', ['user:' . $profile->getId()]) + ->setAttribute('$read', ['user:' . $profile->getId()]) + ->setAttribute('$write', ['user:' . $profile->getId()]) ); $profile->setAttribute('sessions', $session, Document::SET_TYPE_APPEND); @@ -498,6 +499,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'sessions' => [], 'tokens' => [], 'memberships' => [], + 'search' => implode(' ', [$userId, $email, $name]), 'deleted' => false ])); } catch (Duplicate $th) { @@ -548,8 +550,8 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Authorization::setRole('user:' . $user->getId()); $session = $dbForInternal->createDocument('sessions', $session - ->setAttribute('$read', ['user:' . $user->getId()]) - ->setAttribute('$write', ['user:' . $user->getId()]) + ->setAttribute('$read', ['user:' . $user->getId()]) + ->setAttribute('$write', ['user:' . $user->getId()]) ); $user = $dbForInternal->updateDocument('users', $user->getId(), $user); @@ -671,6 +673,7 @@ App::post('/v1/account/sessions/anonymous') 'sessions' => [], 'tokens' => [], 'memberships' => [], + 'search' => $userId, 'deleted' => false ])); @@ -1039,7 +1042,10 @@ App::patch('/v1/account/name') /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ - $user = $dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('name', $name)); + $user = $dbForInternal->updateDocument('users', $user->getId(), $user + ->setAttribute('name', $name) + ->setAttribute('search', implode(' ', [$user->getId(), $name, $user->getAttribute('email')])) + ); $audits ->setParam('userId', $user->getId()) @@ -1138,11 +1144,18 @@ App::patch('/v1/account/email') } $email = \strtolower($email); + $profile = $dbForInternal->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address + + if ($profile) { + throw new Exception('User already registered', 409); + } + try { $user = $dbForInternal->updateDocument('users', $user->getId(), $user ->setAttribute('password', $isAnonymousUser ? Auth::passwordHash($password) : $user->getAttribute('password', '')) ->setAttribute('email', $email) ->setAttribute('emailVerification', false) // After this user needs to confirm mail again + ->setAttribute('search', implode(' ', [$user->getId(), $user->getAttribute('name'), $user->getAttribute('email')])) ); } catch(Duplicate $th) { throw new Exception('Email already exists', 409); @@ -1595,10 +1608,9 @@ App::put('/v1/account/recovery') ); /** - * We act like we're updating and validating - * the recovery token but actually we don't need it anymore. - */ - + * We act like we're updating and validating + * the recovery token but actually we don't need it anymore. + */ foreach ($tokens as $key => $token) { if ($recovery === $token->getId()) { $recovery = $token; @@ -1766,9 +1778,9 @@ App::put('/v1/account/verification') $profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true)); /** - * We act like we're updating and validating - * the verification token but actually we don't need it anymore. - */ + * We act like we're updating and validating + * the verification token but actually we don't need it anymore. + */ foreach ($tokens as $key => $token) { if ($token->getId() === $verification) { $verification = $token; diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index f82219c1eb..d20632b201 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -209,12 +209,6 @@ App::get('/v1/database/collections') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - $queries = []; - - if (!empty($search)) { - $queries[] = new Query('name', Query::TYPE_SEARCH, [$search]); - } - if (!empty($after)) { $afterCollection = $dbForInternal->getDocument('collections', $after); @@ -223,6 +217,12 @@ App::get('/v1/database/collections') } } + $queries = []; + + if (!empty($search)) { + $queries[] = new Query('name', Query::TYPE_SEARCH, [$search]); + } + $usage->setParam('database.collections.read', 1); $response->dynamic(new Document([ diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 2a67c6d4c6..00ed181239 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -53,8 +53,9 @@ App::post('/v1/functions') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ + $functionId = ($functionId == 'unique()') ? $dbForInternal->getId() : $functionId; $function = $dbForInternal->createDocument('functions', new Document([ - '$id' => $functionId == 'unique()' ? $dbForInternal->getId() : $functionId, + '$id' => $functionId, 'execute' => $execute, 'dateCreated' => time(), 'dateUpdated' => time(), @@ -68,6 +69,7 @@ App::post('/v1/functions') 'schedulePrevious' => 0, 'scheduleNext' => 0, 'timeout' => $timeout, + 'search' => implode(' ', [$functionId, $name, $runtime]), ])); $response->setStatusCode(Response::STATUS_CODE_CREATED); @@ -96,8 +98,6 @@ App::get('/v1/functions') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - if (!empty($after)) { $afterFunction = $dbForInternal->getDocument('functions', $after); @@ -105,6 +105,12 @@ App::get('/v1/functions') throw new Exception("Function '{$after}' for the 'after' value not found.", 400); } } + + $queries = []; + + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } $response->dynamic(new Document([ 'functions' => $dbForInternal->find('functions', $queries, $limit, $offset, [], [$orderType], $afterFunction ?? null), @@ -271,6 +277,7 @@ App::put('/v1/functions/:functionId') 'schedule' => $schedule, 'scheduleNext' => (int)$next, 'timeout' => $timeout, + 'search' => implode(' ', [$functionId, $name, $function->getAttribute('runtime')]), ]))); if ($next && $schedule !== $original) { @@ -447,8 +454,9 @@ App::post('/v1/functions/:functionId/tags') throw new Exception('Failed moving file', 500); } + $tagId = $dbForInternal->getId(); $tag = $dbForInternal->createDocument('tags', new Document([ - '$id' => $dbForInternal->getId(), + '$id' => $tagId, '$read' => [], '$write' => [], 'functionId' => $function->getId(), @@ -456,6 +464,7 @@ App::post('/v1/functions/:functionId/tags') 'command' => $command, 'path' => $path, 'size' => $size, + 'search' => implode(' ', [$tagId, $command]), ])); $usage @@ -495,8 +504,6 @@ App::get('/v1/functions/:functionId/tags') throw new Exception('Function not found', 404); } - $queries[] = new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]); - if (!empty($after)) { $afterTag = $dbForInternal->getDocument('tags', $after); @@ -505,6 +512,14 @@ App::get('/v1/functions/:functionId/tags') } } + $queries = []; + + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } + + $queries[] = new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]); + $results = $dbForInternal->find('tags', $queries, $limit, $offset, [], [$orderType], $afterTag ?? null); $sum = $dbForInternal->count('tags', $queries, APP_LIMIT_COUNT); @@ -665,8 +680,10 @@ App::post('/v1/functions/:functionId/executions') Authorization::disable(); + $executionId = $dbForInternal->getId(); + $execution = $dbForInternal->createDocument('executions', new Document([ - '$id' => $dbForInternal->getId(), + '$id' => $executionId, '$read' => (!$user->isEmpty()) ? ['user:' . $user->getId()] : [], '$write' => [], 'dateCreated' => time(), @@ -678,6 +695,7 @@ App::post('/v1/functions/:functionId/executions') 'stdout' => '', 'stderr' => '', 'time' => 0.0, + 'search' => implode(' ', [$functionId, $executionId]), ])); Authorization::reset(); @@ -732,10 +750,11 @@ App::get('/v1/functions/:functionId/executions') ->param('functionId', '', new UID(), 'Function unique ID.') ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('after', '', new UID(), 'ID of the execution used as the starting point for the query, excluding the execution itself. Should be used for efficient pagination when working with large sets of data.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($functionId, $limit, $offset, $after, $response, $dbForInternal) { + ->action(function ($functionId, $limit, $offset, $search, $after, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ @@ -755,13 +774,17 @@ App::get('/v1/functions/:functionId/executions') } } - $results = $dbForInternal->find('executions', [ - new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]), - ], $limit, $offset, [], [Database::ORDER_DESC], $afterExecution ?? null); + $queries = [ + new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]) + ]; - $sum = $dbForInternal->count('executions', [ - new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]), - ], APP_LIMIT_COUNT); + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } + + $results = $dbForInternal->find('executions', $queries, $limit, $offset, [], [Database::ORDER_DESC], $afterExecution ?? null); + + $sum = $dbForInternal->count('executions', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ 'executions' => $results, diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 2acb095a2a..bc20bfdeac 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -79,6 +79,7 @@ App::post('/v1/projects') $auths[$method['key'] ?? ''] = true; } + $projectId = ($projectId == 'unique()') ? $dbForConsole->getId() : $projectId; $project = $dbForConsole->createDocument('projects', new Document([ '$id' => $projectId == 'unique()' ? $dbForConsole->getId() : $projectId, '$read' => ['team:' . $teamId], @@ -101,7 +102,8 @@ App::post('/v1/projects') 'webhooks' => null, 'keys' => null, 'domains' => null, - 'auths' => $auths + 'auths' => $auths, + 'search' => implode(' ', [$projectId, $name]), ])); $collections = Config::getParam('collections2', []); /** @var array $collections */ @@ -173,8 +175,6 @@ App::get('/v1/projects') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ - $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - if (!empty($after)) { $afterProject = $dbForConsole->getDocument('projects', $after); @@ -183,6 +183,12 @@ App::get('/v1/projects') } } + $queries = []; + + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } + $results = $dbForConsole->find('projects', $queries, $limit, $offset, [], [$orderType], $afterProject ?? null); $sum = $dbForConsole->count('projects', $queries, APP_LIMIT_COUNT); @@ -358,6 +364,7 @@ App::patch('/v1/projects/:projectId') ->setAttribute('legalCity', $legalCity) ->setAttribute('legalAddress', $legalAddress) ->setAttribute('legalTaxId', $legalTaxId) + ->setAttribute('search', implode(' ', [$projectId, $name])) ); $response->dynamic($project, Response::MODEL_PROJECT); @@ -460,7 +467,7 @@ App::patch('/v1/projects/:projectId/auth/limit') $auths['limit'] = $limit; $dbForConsole->updateDocument('projects', $project->getId(), $project - ->setAttribute('auths', $auths) + ->setAttribute('auths', $auths) ); $response->dynamic($project, Response::MODEL_PROJECT); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 7ea048c5b3..6c94494527 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -125,13 +125,14 @@ App::post('/v1/storage/files') $sizeActual = $device->getFileSize($path); + $fileId = ($fileId == 'unique()') ? $dbForInternal->getId() : $fileId; $file = $dbForInternal->createDocument('files', new Document([ - '$id' => $fileId == 'unique()' ? $dbForInternal->getId() : $fileId, + '$id' => $fileId, '$read' => (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? [], // By default set read permissions for user '$write' => (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? [], // By default set write permissions for user 'dateCreated' => \time(), 'bucketId' => '', - 'name' => $file['name'], + 'name' => $file['name'] ?? '', 'path' => $path, 'signature' => $device->getFileHash($path), 'mimeType' => $mimeType, @@ -143,6 +144,7 @@ App::post('/v1/storage/files') 'openSSLCipher' => OpenSSL::CIPHER_AES_128_GCM, 'openSSLTag' => \bin2hex($tag), 'openSSLIV' => \bin2hex($iv), + 'search' => implode(' ', [$fileId, $file['name'] ?? '',]), ])); $audits @@ -185,8 +187,6 @@ App::get('/v1/storage/files') /** @var Utopia\Database\Database $dbForInternal */ /** @var Appwrite\Stats\Stats $usage */ - $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : []; - if (!empty($after)) { $afterFile = $dbForInternal->getDocument('files', $after); @@ -195,6 +195,12 @@ App::get('/v1/storage/files') } } + $queries = []; + + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } + $usage ->setParam('storage.files.read', 1) ->setParam('bucketId', 'default') diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 9926f2f3b1..fcb5aeb5c0 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -57,6 +57,7 @@ App::post('/v1/teams') 'name' => $name, 'sum' => ($isPrivilegedUser || $isAppUser) ? 0 : 1, 'dateCreated' => \time(), + 'search' => implode(' ', [$teamId, $name]), ])); Authorization::reset(); @@ -107,8 +108,6 @@ App::get('/v1/teams') /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - if (!empty($after)) { $afterTeam = $dbForInternal->getDocument('teams', $after); @@ -117,6 +116,12 @@ App::get('/v1/teams') } } + $queries = []; + + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } + $results = $dbForInternal->find('teams', $queries, $limit, $offset, [], [$orderType], $afterTeam ?? null); $sum = $dbForInternal->count('teams', $queries, APP_LIMIT_COUNT); @@ -179,7 +184,10 @@ App::put('/v1/teams/:teamId') throw new Exception('Team not found', 404); } - $team = $dbForInternal->updateDocument('teams', $team->getId(), $team->setAttribute('name', $name)); + $team = $dbForInternal->updateDocument('teams', $team->getId(),$team + ->setAttribute('name', $name) + ->setAttribute('search', implode(' ', [$teamId, $name])) + ); $response->dynamic($team, Response::MODEL_TEAM); }); @@ -323,6 +331,7 @@ App::post('/v1/teams/:teamId/memberships') 'sessions' => [], 'tokens' => [], 'memberships' => [], + 'search' => implode(' ', [$userId, $email, $name]), ])); } catch (Duplicate $th) { throw new Exception('Account already exists', 409); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 86319ea5ec..99748d40d5 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -66,6 +66,7 @@ App::post('/v1/users') 'sessions' => [], 'tokens' => [], 'memberships' => [], + 'search' => implode(' ', [$userId, $email, $name]), 'deleted' => false ])); } catch (Duplicate $th) { @@ -107,25 +108,26 @@ App::get('/v1/users') if (!empty($after)) { $afterUser = $dbForInternal->getDocument('users', $after); - if ($afterUser->isEmpty() || $afterUser->getAttribute('deleted')) { - throw new Exception('User for after not found', 400); + if ($afterUser->isEmpty()) { + throw new Exception("User '{$after}' for the 'after' value not found.", 400); } } - $results = $dbForInternal->find('users', [ - new Query('deleted', Query::TYPE_EQUAL, [false]), - ], $limit, $offset, [], [$orderType], $afterUser ?? null); - $sum = $dbForInternal->count('users', [ - new Query('deleted', Query::TYPE_EQUAL, [false]), - ], APP_LIMIT_COUNT); - + $queries = [ + new Query('deleted', Query::TYPE_EQUAL, [false]) + ]; + + if (!empty($search)) { + $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); + } + $usage ->setParam('users.read', 1) ; $response->dynamic(new Document([ - 'users' => $results, - 'sum' => $sum, + 'users' => $dbForInternal->find('users', $queries, $limit, $offset, [], [$orderType], $afterUser ?? null), + 'sum' => $dbForInternal->count('users', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_USER_LIST); }); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index cb820b45c3..57b8ad9218 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -78,6 +78,45 @@ class FunctionsCustomServerTest extends Scope * Test for SUCCESS */ + /** + * Test search queries + */ + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $data['functionId'] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(1, $response['body']['functions']); + $this->assertEquals($response['body']['functions'][0]['name'], 'Test'); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Test' + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(1, $response['body']['functions']); + $this->assertEquals($response['body']['functions'][0]['$id'], $data['functionId']); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'php-8.0' + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(1, $response['body']['functions']); + $this->assertEquals($response['body']['functions'][0]['$id'], $data['functionId']); + + /** + * Test pagination + */ $response = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -122,7 +161,6 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $response['body']['functions']); $this->assertEquals($response['body']['functions'][0]['name'], 'Test 2'); - return $data; } @@ -283,6 +321,48 @@ class FunctionsCustomServerTest extends Scope $this->assertIsArray($function['body']['tags']); $this->assertCount(1, $function['body']['tags']); + /** + * Test search queries + */ + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/tags', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders(), [ + 'search' => $data['functionId'] + ])); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertEquals($function['body']['sum'], 1); + $this->assertIsArray($function['body']['tags']); + $this->assertCount(1, $function['body']['tags']); + $this->assertEquals($function['body']['tags'][0]['$id'], $data['tagId']); + + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/tags', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders(), [ + 'search' => 'Test' + ])); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertEquals($function['body']['sum'], 1); + $this->assertIsArray($function['body']['tags']); + $this->assertCount(1, $function['body']['tags']); + $this->assertEquals($function['body']['tags'][0]['$id'], $data['tagId']); + + $function = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/tags', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders(), [ + 'search' => 'php-8.0' + ])); + + $this->assertEquals($function['headers']['status-code'], 200); + $this->assertEquals($function['body']['sum'], 1); + $this->assertIsArray($function['body']['tags']); + $this->assertCount(1, $function['body']['tags']); + $this->assertEquals($function['body']['tags'][0]['$id'], $data['tagId']); + return $data; } @@ -394,6 +474,36 @@ class FunctionsCustomServerTest extends Scope $this->assertCount(1, $function['body']['executions']); $this->assertEquals($function['body']['executions'][0]['$id'], $data['executionId']); + /** + * Test search queries + */ + + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $data['executionId'], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['executions']); + $this->assertEquals($data['functionId'], $response['body']['executions'][0]['functionId']); + + $response = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $data['functionId'], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['executions']); + $this->assertEquals($data['executionId'], $response['body']['executions'][0]['$id']); + return $data; } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 6bde76dc11..2572c7e096 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -87,6 +87,7 @@ class ProjectsConsoleClientTest extends Scope /** * Test for SUCCESS */ + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -97,6 +98,35 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals($id, $response['body']['projects'][0]['$id']); $this->assertEquals('Project Test', $response['body']['projects'][0]['name']); + /** + * Test search queries + */ + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders(), [ + 'search' => $id + ])); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertEquals($response['body']['sum'], 1); + $this->assertIsArray($response['body']['projects']); + $this->assertCount(1, $response['body']['projects']); + $this->assertEquals($response['body']['projects'][0]['name'], 'Project Test'); + + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders(), [ + 'search' => 'Project Test' + ])); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertEquals($response['body']['sum'], 1); + $this->assertIsArray($response['body']['projects']); + $this->assertCount(1, $response['body']['projects']); + $this->assertEquals($response['body']['projects'][0]['$id'], $data['projectId']); + /** * Test after pagination */ diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index 57a5ee6972..ab1a08c682 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -163,7 +163,7 @@ trait StorageBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'fileId' => 'unique()', - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/file.png'), 'image/png', 'file.png'), 'read' => ['role:all'], 'write' => ['role:all'], ]); @@ -171,9 +171,9 @@ trait StorageBase $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($file['body']['$id']); $this->assertIsInt($file['body']['dateCreated']); - $this->assertEquals('logo.png', $file['body']['name']); - $this->assertEquals('image/png', $file['body']['mimeType']); - $this->assertEquals(47218, $file['body']['sizeOriginal']); + $this->assertEquals('file.png', $file['body']['name']); + $this->assertEquals('image/jpeg', $file['body']['mimeType']); + $this->assertEquals(16804, $file['body']['sizeOriginal']); $files = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ 'content-type' => 'application/json', @@ -197,6 +197,32 @@ trait StorageBase $this->assertEquals($files['body']['files'][1]['$id'], $response['body']['files'][0]['$id']); $this->assertCount(1, $response['body']['files']); + $response = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $data['fileId'], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['files']); + $this->assertEquals('logo.png', $response['body']['files'][0]['name']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'logo', + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['files']); + $this->assertEquals($data['fileId'], $response['body']['files'][0]['$id']); + /** * Test for FAILURE */ diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 6c1ebbe36a..b594bbfa67 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -172,6 +172,19 @@ trait TeamsBase $this->assertCount(1, $response['body']['teams']); $this->assertEquals('Manchester United', $response['body']['teams'][0]['name']); + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $data['teamUid'], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertGreaterThan(0, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['teams']); + $this->assertEquals('Arsenal', $response['body']['teams'][0]['name']); + $teams = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index 90b59a8c16..ee35e66fc3 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -16,14 +16,14 @@ trait UsersBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'userId' => 'unique()', - 'email' => 'users.service@example.com', + 'email' => 'cristiano.ronaldo@manchester-united.co.uk', 'password' => 'password', - 'name' => 'Project User', + 'name' => 'Cristiano Ronaldo', ]); $this->assertEquals($user['headers']['status-code'], 201); - $this->assertEquals($user['body']['name'], 'Project User'); - $this->assertEquals($user['body']['email'], 'users.service@example.com'); + $this->assertEquals($user['body']['name'], 'Cristiano Ronaldo'); + $this->assertEquals($user['body']['email'], 'cristiano.ronaldo@manchester-united.co.uk'); $this->assertEquals($user['body']['status'], true); $this->assertGreaterThan(0, $user['body']['registration']); @@ -35,15 +35,15 @@ trait UsersBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'userId' => 'user1', - 'email' => 'users.service1@example.com', + 'email' => 'lionel.messi@psg.fr', 'password' => 'password', - 'name' => 'Project User', + 'name' => 'Lionel Messi', ]); $this->assertEquals($res['headers']['status-code'], 201); $this->assertEquals($res['body']['$id'], 'user1'); - $this->assertEquals($res['body']['name'], 'Project User'); - $this->assertEquals($res['body']['email'], 'users.service1@example.com'); + $this->assertEquals($res['body']['name'], 'Lionel Messi'); + $this->assertEquals($res['body']['email'], 'lionel.messi@psg.fr'); $this->assertEquals(true, $res['body']['status']); $this->assertGreaterThan(0, $res['body']['registration']); @@ -56,7 +56,7 @@ trait UsersBase public function testListUsers(array $data): void { /** - * Test for SUCCESS + * Test for SUCCESS listUsers */ $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ 'content-type' => 'application/json', @@ -82,8 +82,72 @@ trait UsersBase $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['users']); $this->assertCount(1, $response['body']['users']); - $this->assertEquals($response['body']['users'][0]['$id'], 'user1'); + + /** + * Test for SUCCESS searchUsers + */ + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'Ronaldo' + ]); + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + $this->assertEquals($response['body']['users'][0]['$id'], $data['userId']); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'cristiano.ronaldo' + ]); + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + $this->assertEquals($response['body']['users'][0]['$id'], $data['userId']); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'manchester' + ]); + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + $this->assertEquals($response['body']['users'][0]['$id'], $data['userId']); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'manchester-united.co.uk' + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertIsArray($response['body']); + $this->assertIsArray($response['body']['users']); + $this->assertIsInt($response['body']['sum']); + $this->assertEquals(1, $response['body']['sum']); + $this->assertCount(1, $response['body']['users']); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => $data['userId'] + ]); + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + $this->assertEquals($response['body']['users'][0]['$id'], $data['userId']); } /** @@ -100,8 +164,8 @@ trait UsersBase ], $this->getHeaders())); $this->assertEquals($user['headers']['status-code'], 200); - $this->assertEquals($user['body']['name'], 'Project User'); - $this->assertEquals($user['body']['email'], 'users.service@example.com'); + $this->assertEquals($user['body']['name'], 'Cristiano Ronaldo'); + $this->assertEquals($user['body']['email'], 'cristiano.ronaldo@manchester-united.co.uk'); $this->assertEquals($user['body']['status'], true); $this->assertGreaterThan(0, $user['body']['registration']); @@ -132,21 +196,6 @@ trait UsersBase $this->assertIsInt($users['body']['sum']); $this->assertGreaterThan(0, $users['body']['sum']); - $users = $this->client->call(Client::METHOD_GET, '/users', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'search' => 'example.com' - ]); - - $this->assertEquals($users['headers']['status-code'], 200); - $this->assertIsArray($users['body']); - $this->assertIsArray($users['body']['users']); - $this->assertIsInt($users['body']['sum']); - $this->assertEquals(2, $users['body']['sum']); - $this->assertGreaterThan(0, $users['body']['sum']); - $this->assertCount(2, $users['body']['users']); - return $data; }